在SQL Server中选择N行

在SQL Server中选择N行,sql,sql-server,tsql,Sql,Sql Server,Tsql,以下查询将在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行。为什么此查询不能返回超

以下查询将在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行

更新

我刚刚找到了另一种方法来达到我的要求,如下所示

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);

如果没有最后一行代码,它会因错误而中断。在语句完成之前,最大递归100已用尽,我发现这一行为无限递归指定了0。但这个问题对我来说似乎有点慢。有什么更快的方法吗?

当变量中的值超过值7374时,这无关紧要。该表只有7374行。

生成大量数字的一种方法是使用交叉联接在两个表之间创建笛卡尔乘积,这将生成一个大小为n^2的集合

但是,这种方法的性能比中提出的解决方案差得多,因此不应使用


在您的案例中,这将生成一组54375876行。你应该考虑创建一个适合你需要的理货表。

< P>这意味着你的查询返回的行总数是7374。如果您可以创建一些表并运行代码,您将看到前面评论的数量的增加,这是因为您达到了sys.columns的行数。这里是另一种生成数字列表或其他人称之为数字表或理货表的方法

这使用级联CTE,据说是创建理货表的最快方法:

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
如果需要超过10000行,可以轻松添加另一个CTE

有关理货台的更多信息,请阅读杰夫·摩登的这篇优秀文章

有关生成理货表的各种方法的性能比较,请阅读

杰夫的解释:

被称为E1的CTE在10E1中表示科学记数法,这算不了什么 作为单个结果集返回的SELECT 1超过十个

E2将E1与自身交叉连接。返回一个 10*10或最多100行的结果集。我说最多是因为如果 TOP功能为100或更少,CTE足够聪明,知道这一点 它实际上不需要再进一步,E4和E8也不会 甚至可以发挥作用。如果顶部的值小于100,则 E2能够生成的所有100行都将生成。永远都是这样 根据TOP函数制作刚好足够的

你可以从那里开始。E4是E2和will的交叉连接 最多可组成100*100或10000行,E8是E4的交叉连接 这将造成比大多数人所需要的更多的争吵。如果你这样做 需要更多,然后只需添加一个E16作为E8的交叉连接并更改 最后一个FROM条款来自E16

这个坏男孩真正令人惊奇的是,它的产量为零 阅读。绝对没有,娜达,没有


这是因为最大行数为7374,您可以使用master..spt_Values表进行自身的交叉连接,您将获得所需持续时间列的6325225值


我使用这个函数来获取运行的数字。您可以直接在FROM或with JOIN或APPLY中使用它

在阅读其他评论后,我将其改为堆叠CTE方法thx至Felix


因为sys.all_列只包含7374行?Thnx@cbranch。。我怎么会错过它!!!使用伊兹克·本·甘的堆叠/级联CTE查看我的答案。如果您想了解处理器冷却技术的效率,可以递归执行此操作。@TanjimRahman,我不建议为此使用递归CTE。正如Eric所评论的,rCTE给您的CPU带来了很高的负载。Itzik Ben Gan的级联CTE比交叉连接要好@FelixPamittan,所以它看起来要快得多。相对成本为8%,而交叉连接的成本为92%。我想我会删除这个答案,因为这是一个低于标准的解决方案,尽管它很有效。@FelixPamittan足够公平。我编辑了一个链接,链接到你的答案:是的,亚伦·伯特朗在系列中测试了各种技术,伊兹克·本·甘的叠加CTE方法在所有的动态方法中脱颖而出。对于50000行,递归CTE甚至无法与其他方法在同一个图形上进行比较,因为它严重扭曲了比例。使用sys.all_列读取CTE不在的行。TOP函数确定实现目标所需的连接数。我说的对吗?@FelixPamittan,你最终会想从E4改成E8。还有:谢谢你这篇好文章@是的!谢谢你接电话。
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
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
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;