是否有一种在SQL中生成任意线性序列的通用方法?

时间:2010-07-13 11:01:31

标签: sql

我可以做一个SQL查询,它会生成一个像

这样的线性序列
1, 2, 3, 4, 5, 6, 7 ... x+1

2, 7, 12, 17, 22 ... 2+5x

(其中每个数字是结果表的一行中的条目)

6 个答案:

答案 0 :(得分:3)

SQL Server和Oracle现在实现ANSI标准ROW_NUMBER()窗口函数,但是您需要一个表来处理:

SELECT ROW_NUMBER() OVER (ORDER BY ID) AS __ROW, ID, Name
FROM SomethingWithANameAndAnID
ORDER BY __ROW;

或者您可以在SQL Server中使用递归公用表表达式(不确定Oracle是否实现了这一点):

WITH cte AS
(
    SELECT 1 AS num
    UNION ALL
    SELECT (num + 1) AS num FROM cte
    WHERE num < @SomeMaximum
)
SELECT * FROM cte OPTION (MAXRECURSION 0);

请注意,如果没有MAXRECURSION选项,MS SQL中的CTE递归深度限制为100.(值0禁用递归限制)

答案 1 :(得分:2)

如果您关注性能,请准备好此UDF:

create function [dbo].[Numbers](@count bigint)
RETURNS TABLE RETURN
with byte (n) as ( select 1 from ( VALUES 
        (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
        ) x(n)  )
, byte2 (n) as ( select 1 from byte a, byte b)
, byte4 (n) as ( select 1 from byte2 a, byte2 b)
, byte8 (n) as ( select 1 from byte4 a, byte4 b)
select top(@count) n = ROW_NUMBER() over(order by n) from byte8

显然,仅递归CTE生成的数字序列有效,但速度很慢。在这里,我们交易一些代码量以大幅提升性能。在我糟糕的PC上,这个让我在8秒钟内获得超过3000万个数字。它可以随心所欲,可以承受max bigint的限制。

除非优化程序将其排除在内存之外,否则它不会触及磁盘IO(几乎没有合理的情况)。与基于物理表的解决方案不同,它还可以避免等待和死锁。

像这样使用:

select 2 + n*5 from Numbers(100)

您应该可以创建这样的视图。

对于那些不需要实际数字的人,只需要删除row_number的行就可以加速两次。

http://weblogs.sqlteam.com/jamesn/archive/2008/05/29/60612.aspx的启发(S. Neumann提到的Itzik Ben Gan)。这个版本附带了一个更简单的执行计划,并使得bigints成为可能,这就是优势。

答案 2 :(得分:1)

没有。 (除非预先创建一个数字表作为通用方法。)

在SQL Server中,可以使用递归CTE或使用ROW_NUMBER()

生成序列来完成此操作

答案 3 :(得分:0)

使用序列

答案 4 :(得分:0)

在Oracle中,你可以这样做:

select ROWNUM linear_sequence from dual CONNECT BY LEVEL <= x;

其中x是序列的结尾。

答案 5 :(得分:0)

您可以在创建序列时指定增量:

CREATE SEQUENCE mysequence  INCREMENT BY 5 START WITH 2;