以下查询将在10行中返回1-10。
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);
但是当我将@Range设置为10000时,它返回7374行。为什么此查询不能返回超过7374行。
更新
我刚刚找到另一种方法来实现我的要求,如下所示
{{1}}
没有最后一行代码,它突然出现错误最大递归100在语句完成之前已经用完了,我发现这行为无限递归指定0。但这个查询对我来说似乎有点慢。有没有更快的方法???
答案 0 :(得分:11)
如前所述,这是因为您达到了sys.columns
的行数。这是另一种生成数字列表或其他人称为Numbers Table
或Tally Table
的方法。
这使用级联CTE
,据说是创建Tally Table的最快方法:
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的这篇优秀article。
对于生成Tally表的方法之间的性能比较,请阅读this。
Jeff的解释article:
CTE称为
E1
(如10E1中的科学记法所示)并不算什么 超过十个SELECT 1
作为单个结果集返回。
E2
自己CROSS JOIN
E1
。这会返回一个 结果集为10 * 10或最多100行。我说&#34;直到&#34;因为如果 TOP功能是100或更少,CTE是&#34; smart&#34;足以知道这一点 它实际上不需要再进一步E4
和E8
赢了 甚至发挥作用。如果TOP
的值小于100,则不是E2
能够制作的所有100行。它永远都是 根据{{1}}函数制作足够的内容。你可以从那里开始。
TOP
是E4
CROSS JOIN
的意思 最多100 * 100或10,000行,E2
是E8
CROSS JOIN
这将比大多数人需要的行数更多。如果你这样做 需要更多,然后只需添加E4
作为E16
的{{1}}并进行更改CROSS JOIN
的最终E8
条款。这个坏孩子真正令人惊讶的是产生 ZERO READS 即可。绝对没有,纳达,没有。
答案 1 :(得分:3)
生成大量数字的一种方法是使用cross join
在两个表之间创建一个笛卡尔积,这将产生一个n^2
大小的集合。
然而,这种方法比the answer by Felix Pamittan中提出的解决方案要糟糕得多,因此不应该使用。
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行。您应该考虑创建一个适合您需求的计数表,而不是动态生成行。
答案 2 :(得分:0)
当变量中的值超过值7374时,这无关紧要。该表只有7374行。
答案 3 :(得分:0)
这意味着您的查询返回的总行数是7374.如果您可以创建一些表并运行代码,您将看到数字的增加
答案 4 :(得分:0)
这是因为最大行数是7374,您可以使用master..spt_Values表进行交叉连接,并且您将获得所需6325225
列的Duration
值。< / p>
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
答案 5 :(得分:0)
我使用此功能来获取正在运行的数字。您可以直接在FROM(或JOIN或APPLY ...)
中使用它在阅读其他评论后,我将其更改为“堆叠CTE”方法(thx to Felix)
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;