带数字的SQL

时间:2018-04-06 15:42:27

标签: sql sql-server

我正在尝试使用SQL Server构建一个循环。

当我执行SELECT 1 UNION SELECT 2 UNION SELECT 3;时,SQL Server会创建一个包含1列和4行的表。

如果不使用UNION

,有人可以想出一种方法来实现相同的目标吗?

5 个答案:

答案 0 :(得分:4)

您可以使用values()表构造函数:

select *
from (values (1), (2), (3), (4)) v(n);

答案 1 :(得分:3)

您可以使用递归cte轻松完成此操作。

declare @max int=4

;with cte as
(
    select 1 as val
    union all
    select val+1
    from cte
    where val < @max
)
select *
from cte

答案 2 :(得分:2)

以下是一些常见的选项,以防您的用例扩展数百或数千行...

通常看到一个理货表...

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

或者,使用Jeff Moden的功能

 CREATE FUNCTION [dbo].[fnTallyProg]
/**********************************************************************************************************************
 Purpose:
 Given a start value, end value, and increment, create a sequencial list of integers.
 Programmers Notes:
 1. The increment can be negative if the start value is greater than the end value. In other words, it can count down
    as well as up.

 Revison History:
 Rev 00 - 18 Feb 2017 - Jeff Moden
        - Rewrite original to take start, end, and increment parameters.
**********************************************************************************************************************/
        (
         @pStart     BIGINT
        ,@pEnd       BIGINT
        ,@pIncrement BIGINT
        )
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN WITH 
 E01(N)   AS (SELECT NULL FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))E0(N)) --10 rows
,E04(N)   AS (SELECT NULL FROM E01 a CROSS JOIN E01 b CROSS JOIN E01 c CROSS JOIN E01 d) --10 Thousand rows
,E16(N)   AS (SELECT NULL FROM E04 a CROSS JOIN E04 b CROSS JOIN E04 c CROSS JOIN E04 d) --10 Quadrillion rows, which is crazy
,Tally(N) AS (SELECT TOP (ABS((@pEnd-@pStart+@pIncrement)/@pIncrement))
                     N = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
                FROM E16
               WHERE (@pStart<=@pEnd AND @pIncrement > 0)
                  OR (@pStart>=@pEnd AND @pIncrement < 0)
               ORDER BY N
             )
      SELECT TOP (ABS((@pEnd-@pStart+@pIncrement)/@pIncrement))
             N = (t.N-1)*@pIncrement+@pStart
        FROM Tally t
       ORDER BY t.N
;
GO

或者,JL的另一个快速功能

CREATE FUNCTION [dbo].[tfn_Tally]
(
@NumOfRows BIGINT = 1000000 
,@StartWith BIGINT = 1563984
)
/* ============================================================================
07/20/2017 JL, Created. Capable of creating a sequense of rows 
                ranging from -10,000,000,000,000,000 to 10,000,000,000,000,000
============================================================================ */
RETURNS TABLE WITH SCHEMABINDING AS 
RETURN
WITH 
        cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),   -- 10 rows
        cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),                             -- 100 rows
        cte_n3 (n) AS (SELECT 1 FROM cte_n2 a CROSS JOIN cte_n2 b),                             -- 10,000 rows
        cte_n4 (n) AS (SELECT 1 FROM cte_n3 a CROSS JOIN cte_n3 b),                             -- 100,000,000 rows
        cte_Tally (n) AS (
            SELECT TOP (@NumOfRows)
                (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) + @StartWith
            FROM 
                cte_n4 a CROSS JOIN cte_n4 b                                                    -- 10,000,000,000,000,000 rows
            )
    SELECT 
        t.n
    FROM 
        cte_Tally t;

答案 3 :(得分:1)

只是为了好玩,您可以使用临时计数表

示例

Declare @N int =4

Select Top (@N) N=Row_Number() Over (Order By (Select NULL)) 
 From  master..spt_values n1

<强>返回

N
1
2
3
4

答案 4 :(得分:1)

如果你需要的是一系列要在以后连接到另一个表的值,我强烈建议创建一个一次性的数字辅助表,如here所述

生成这样的表的代码非常基本:

SELECT TOP (1000000) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO dbo.Numbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(n)

这将创造一个持久的&#34;数字&#34;数据库中的表,然后您可以使用它来连接到其他表或使用函数。