SQL选择没有表的'n'记录

时间:2011-06-30 10:40:53

标签: sql sql-server tsql

有没有办法在不创建表的情况下选择特定行数。例如如果我使用以下内容:

SELECT 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

它会给我10个,我想要10个新行。

由于

8 个答案:

答案 0 :(得分:29)

您可以使用recursive CTE在T-SQL中生成任意数字序列,如下所示:

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

答案 1 :(得分:18)

如果您有固定的行数,可以尝试:

SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
UNION
SELECT 10

答案 2 :(得分:7)

如果你需要一个长列表,这是一个很好的方法(所以你不需要很多UNION语句:

WITH CTE_Numbers AS (
    SELECT n = 1
    UNION ALL
    SELECT n + 1 FROM CTE_Numbers WHERE n < 10 
)
SELECT n FROM CTE_Numbers

答案 3 :(得分:7)

递归CTE方法 - 非常好。

只是意识到性能差异。让我们玩上百万条记录:

递归CTE方法。持续时间= 14秒

declare @start int = 1;
declare @end int = 999999;

with numbers as 
(
    select @start as number
    union all
    select number + 1 from numbers where number < @end
)
select * from numbers option(maxrecursion 0);

Union All + Cross Join方法。持续时间= 6秒

with N(n) as 
(
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all select 1   
)
select top 999999
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6;

表值构造函数+交叉连接方法。持续时间= 6秒

(如果SQL Server&gt; = 2008)

with N as 
(
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)    
)   
select top 999999
    row_number() over(order by (select 1)) as number
from 
    N n1, N n2, N n3, N n4, N n5, N n6;

递归CTE +交叉连接方法。 :)持续时间= 6秒

with N(n) as 
(
    select 1 
    union all
    select n + 1 from N where n < 10    
)   
select top 999999
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6;

如果我们尝试将结果INSERT到表变量中,我们将获得更多惊人的效果:

使用递归CTE方法插入INTO。持续时间= 17秒

declare @R table (Id int primary key clustered);

with numbers as 
(
    select 1 as number
    union all
    select number + 1 from numbers where number < 999999
)
insert into @R 
select * from numbers option(maxrecursion 0);

使用交叉连接方法插入INTO。持续时间= 1秒

declare @C table (Id int primary key clustered);

with N as 
(
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)    
) 
insert into @C 
select top 999999
    row_number() over(order by (select 1)) as number
from 
    N n1, N n2, N n3, N n4, N n5, N n6;

这是一篇关于Tally Tables

的有趣文章

答案 4 :(得分:4)

SELECT 1
UNION 
SELECT 2
UNION
...
UNION
SELECT 10 ;

答案 5 :(得分:2)

使用PIVOT(在某些情况下会有点矫枉过正)

DECLARE @Items TABLE(a int, b int, c int, d int, e int); 

INSERT INTO @Items
VALUES(1, 2, 3, 4, 5)

SELECT Items 
FROM @Items as p 
UNPIVOT     
(Items FOR Seq IN          
([a], [b], [c], [d], [e]) ) AS unpvt 

答案 6 :(得分:1)

使用spt_values表:

SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY number) 
FROM [master]..spt_values ORDER BY n;

或者,如果所需的值小于1k:

SELECT DISTINCT n = number FROM master..[spt_values] WHERE number BETWEEN 1 AND 1000;
  

这是内部存储过程用于各种目的的表。它在网上的使用似乎非常普遍,即使它没有文档,不受支持,它可能有一天消失,因为它只包含一组有限的,非唯一的和非连续的值。 SQL Server 2008 R2中共有2,164个唯一值和2,508个值; 2012年有2,167个独特和2,515个。这包括重复,负值,即使使用DISTINCT,一旦超出数字2,048,就会有很多空白。因此,解决方法是使用ROW_NUMBER()根据表中的值从1开始生成连续序列。

此外,为了提供超过2k记录的更多值,您可以将表连接到自身,但在通常情况下,该表本身就足够了。

性能方面,它不应该太糟糕(生成一百万条记录,我的笔记本电脑需要10秒钟),并且查询非常容易阅读。

来源:http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

答案 7 :(得分:0)

;WITH nums AS
    (SELECT 1 AS value
    UNION ALL
    SELECT value + 1 AS value
    FROM nums
    WHERE nums.value <= 99)
SELECT *
FROM nums