在SQL Server中selectN行

以下查询将在10行中返回1-10。

DECLARE @Range AS INT = 10 ;WITH CTE AS( SELECT TOP (@Range) Duration = ROW_NUMBER() OVER(ORDER BY OBJECT_ID) FROM sys.all_columns ORDER BY [Object_id] ) SELECT Duration from CTE 

但是当我将@Range设置为10000时,它返回7374行。 为什么这个查询不能返回超过7374行。

UPDATE

我刚刚find另一种方法来达到我的要求如下

 DECLARE @start INT = 1; DECLARE @end INT = 10; WITH numbers AS ( SELECT @start AS number UNION ALL SELECT number + 1 FROM numbers WHERE number < @end ) SELECT * FROM numbers OPTION (MAXRECURSION 0); 

没有最后一行代码它打破了错误最大recursion100已经耗尽语句完成之前,我发现这行是无限recursion指定0。 但是这个查询似乎对我来说慢一点。 有没有更快的方法?

如前所述,这是因为您达到了sys.columns的行数。 这是另一种生成数字列表的方法,或者其他人称之为Numbers Table或“ Tally Table

这使用级联的CTE ,据说是创build一个Tally表的最快方法:

 DECLARE @Range AS INT = 7374 ;WITH E1(N) AS( -- 10 ^ 1 = 10 rows SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N) ), E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b), -- 10 ^ 8 = 10,000,000 rows CteTally(N) AS( SELECT TOP(@Range) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) FROM E8 ) SELECT * FROM CteTally 

如果您需要超过10,000行,则可以轻松添加另一个CTE。

有关Tally Table的更多信息,请阅读Jeff Moden 撰写的优秀文章

为了在生成Tally表的方法之间进行性能比较,请阅读。


杰夫的文章解释:

称为E1的CTE(如在10E1中用于科学记数法)不过是十个SELECT 1作为单个结果集而返回。

E2与自己的E1进行CROSS JOIN 。 这将返回一个10 * 10或最多100行的单个结果集。 我说“高达”,因为如果TOPfunction是100或更less,CTE是“聪明的”,足以知道它实际上不需要进一步, E4E8甚至不会发挥作用。 如果TOP的值小于100,则不能产生E2能够产生的100行。 根据TOPfunction,它总是能够做到。

你可以从那里跟随。 E4E2一个CROSS JOIN ,最多可以组成100 * 100或10,000行,而E8E4CROSS JOIN ,这将会比大多数人所需要的更多的行数。 如果你需要更多的东西,那么只需要添加一个E16作为E8CROSS JOIN ,并将最后的FROM子句改为FROM E16

这个坏男孩真的很棒,那就是产生零读写 。 绝对没有,纳达,零。

生成大量数字的一种方法是使用cross join在两个表之间创build一个笛卡尔积,这将生成一个n^2大小的集合。

然而,这种方法比Felix Pamittan提出的解决scheme的解决scheme要差得多,因此不应该使用。

 DECLARE @Range AS INT = 10000 ;WITH CTE AS( SELECT TOP (@Range) Duration = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM sys.all_columns a CROSS JOIN sys.all_columns b ) SELECT Duration from CTE 

这会在你的情况下产生一组54375876行。 不要dynamic地生成行,您应该考虑创build一个适合您的需求的理货表。

当variables中的值超过值7374时,这并不重要。 该表只有7374行。

这意味着查询返回的总行数为7374.如果您可以创build一些表并运行代码,则会看到数量增加

这是因为行的最大数量是7374,你可以使用master..spt_Values表来交叉连接本身,你会得到6325225你想要的Duration列的值。

 DECLARE @Range AS INT = 10000 ;WITH CTE AS( SELECT TOP (@Range) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) Duration FROM master..spt_values a cross join master..spt_values b ) SELECT Duration from CTE 

我使用这个函数来获得运行数字。 您可以直接在FROM中使用它(或使用JOIN或APPLY …)

阅读其他评论后,我改变了这个“堆叠CTE”的方法(thx费利克斯)

 CREATE FUNCTION [dbo].[GetRunningNumbers](@anzahl INT=10000000, @StartAt INT=0) RETURNS TABLE AS RETURN WITH E1(N) AS( -- 10 ^ 1 = 10 rows SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N) ), E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b), -- 10 ^ 8 = 10,000,000 rows CteTally AS( SELECT TOP(ISNULL(@anzahl,1000000)) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) -1 + ISNULL(@StartAt,0) As Nmbr FROM E8 ) SELECT * FROM CteTally;