【问题标题】:SQL Server - Range NumberSQL Server - 范围号
【发布时间】:2019-08-01 07:03:05
【问题描述】:

我需要您的帮助才能从给定的输入中获得以下输出。

输入

表:Sample

ID
---
1
2
3
4

输出

ID
---
1
2
2
3
3
3
4
4
4
4

【问题讨论】:

    标签: sql sql-server tsql sql-server-2012


    【解决方案1】:

    使用自联接:

    select s.id
    from sample s inner join sample ss
    on s.id >= ss.id 
    order by s.id
    

    请参阅demo
    结果:

    > | id |
    > | -: |
    > |  1 |
    > |  2 |
    > |  2 |
    > |  3 |
    > |  3 |
    > |  3 |
    > |  4 |
    > |  4 |
    > |  4 |
    > |  4 |
    

    如果 id 之间存在间隙或最小值大于 1,您可以使用递归 CTE:

    declare @maxid int = (select max(id) from sample);
    with allids AS (
      select 1 id
      union all
      select id + 1 FROM allids where id + 1 <= @maxid
    )
    select s.id
    from sample s inner join allids ss
    on s.id >= ss.id
    order by s.id
    

    请参阅demo

    INSERT INTO Sample ( ID ) VALUES ( 2 ), ( 3 ), ( 5 ), ( 7 ), ( 9 );
    

    结果:

    > | id |
    > | -: |
    > |  2 |
    > |  2 |
    > |  3 |
    > |  3 |
    > |  3 |
    > |  5 |
    > |  5 |
    > |  5 |
    > |  5 |
    > |  5 |
    > |  7 |
    > |  7 |
    > |  7 |
    > |  7 |
    > |  7 |
    > |  7 |
    > |  7 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    > |  9 |
    

    使用此解决方案您不必对表的 id 进行硬编码(可以有多少个?),即使您添加或删除 id 也可以使用.

    【讨论】:

      【解决方案2】:

      这是一个解决方案

      SELECT ID
      FROM (VALUES (1), (2), (3), (4)) T(ID)
      CROSS APPLY
      (
        SELECT 1 N
        FROM master..spt_values
        WHERE [Type] = 'P'
              AND
              [Number] < T.ID
      ) TT(V);
      

      Demo

      为什么使用spt_values 而不是自加入?

      例如,如果您没有值 3

      SELECT T.ID
      FROM (VALUES (1), (2), (4)) T(ID)
      INNER JOIN (VALUES (1), (2), (4)) TT(ID)
      ON T.ID >= TT.ID 
      ORDER BY T.ID;
      

      slef-join 将重复值4 三次而不是四次。 使用spt_values 将保证每个数字都会按预期重复。

      SELECT T.ID
      FROM (VALUES (1), (2), (4)) T(ID)
      CROSS APPLY
      (
        SELECT 1 N
        FROM master..spt_values
        WHERE [Type] = 'P'
              AND
              [Number] < T.ID
      ) TT(V);
      

      Demo


      如果你有很多数字,那么你可以使用 Tally Table 作为

      CREATE VIEW Tally (N) AS
      SELECT ROW_NUMBER() OVER(ORDER BY(SELECT 0)) N
      FROM (
             (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T1(N) --10
             CROSS JOIN
             (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T2(N) --100
             CROSS JOIN
             (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T3(N) --1000
             CROSS JOIN
             (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T5(N) --10000
           );
      SELECT T.V
      FROM (VALUES (1), (2), (4), (80), (4000)) T(V)
      CROSS APPLY (SELECT N FROM Tally WHERE N <= T.V) TBL
      ORDER BY T.V;
      

      这是db<>fiddle

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-11
        • 2014-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多