【问题标题】:Creating sequence in SQL with different length在 SQL 中创建不同长度的序列
【发布时间】:2017-10-06 18:58:09
【问题描述】:

我有一个表格,客户标识符为 PK,他的到期时间以月为单位:

Customer |  Maturity
---------+-----------
1             80
2             60
3             52
4             105

我想创建一个包含客户标识符的表,并且成熟度将定义为增量 + 1 的数字序列:

Customer |  Maturity
---------+------------
1             1
1             2
1            ....
1             80
2             1
2             2
2            ...
2             60

我不知道我应该使用序列还是交叉连接或如何解决这个问题。

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

一种方法是使用递归 CTE。

; with cte as
(
    select  Customer, M = 1, Maturity
    from    yourtable
    union all
    select  Customer, M = M + 1, Maturity
    from    yourtable
    where   M < Maturity
)
select  *
from    cte
option (MAXRECURSION  0)

【讨论】:

    【解决方案2】:

    您可以尝试将当前表连接到序列表以生成所需的成熟度范围。

    WITH cte AS (
        SELECT 1 AS seq
        UNION ALL
        SELECT seq + 1
        FROM cte
        WHERE seq < 500
    )
    
    SELECT
        t1.Customer,
        t2.seq AS Maturity
    FROM yourTable t1
    INNER JOIN cte t2
        ON t2.seq <= t1.Maturity
    ORDER BY
        t1.Customer,
        t2.seq
    OPTION (MAXRECURSION 0);
    

    演示在这里:

    Rextester

    【讨论】:

      【解决方案3】:

      您可以尝试如下查询

      create table t (Customer int,  Maturity int)
      insert into t values 
      (1,80)
      ,(2,60)
      ,(3,52)
      ,(4,105);
      
      select Customer, r from 
      t cross join
      (select top (select max(maturity) from t)
      row_number() over( order by (select NULL)) r 
      from sys.objects s1 cross join sys.objects s2) k
      where r<=Maturity
      order by Customer asc,r asc
      

      see live demo

      【讨论】:

        【解决方案4】:

        你可以试试下面的。 在下面的示例中创建了两个临时表来表示您的表。 您需要将它们替换为您的表名并删除前三行。

        declare @Customer table (Customer int, Maturity int)
        declare @NewTable table (Customer int, Maturity int)
        insert @Customer select 1, 80
        
        declare @x int = 0
        declare @iterations table (x int)
        while @x <= (select max(Maturity) from @Customer)
        begin
            set @x += 1
            insert @iterations select @x
        end
        
        insert @NewTable
        select  c.Customer, i.x from @Customer c left join @iterations i on i.x <= c.Maturity
        
        select * from @NewTable
        

        【讨论】:

          【解决方案5】:

          延迟回答,但另一种选择是与 CROSS APPLY 配合使用的临时计数表

          示例

          Select A.customer 
                ,Maturity = B.N
           From  YourTable A
           Cross Apply (
                          Select Top (A.Maturity) N=Row_Number() Over (Order By (Select NULL)) 
                            From master..spt_values n1
                       ) B
          

          【讨论】:

          • 我最喜欢你的回答,因为你的 r 使用简单的数字表,如果数字表是永久的,那么查询就更简单了。
          • @KumarHarsh 实际上任何适当大小的表都可以。 spt_values 有 2,500 条记录。如果您需要更多,您可以使用 master..spt_values n1, master..spt_values n2 最多有 6,365,529 条记录
          猜你喜欢
          • 1970-01-01
          • 2020-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-22
          • 1970-01-01
          • 1970-01-01
          • 2016-03-11
          相关资源
          最近更新 更多