在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是“聪明的”,足以知道它实际上不需要进一步,E4
和E8
甚至不会发挥作用。 如果TOP
的值小于100,则不能产生E2
能够产生的100行。 根据TOP
function,它总是能够做到。你可以从那里跟随。
E4
是E2
一个CROSS JOIN
,最多可以组成100 * 100或10,000行,而E8
是E4
的CROSS JOIN
,这将会比大多数人所需要的更多的行数。 如果你需要更多的东西,那么只需要添加一个E16
作为E8
的CROSS 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;