【问题标题】:How to select multiple ranges seperated by group id如何选择按组 ID 分隔的多个范围
【发布时间】:2019-04-24 23:49:01
【问题描述】:

我需要为表中的每个组 id 创建一个逗号分隔的值列表并填写所有缺失值,但我不太确定如何继续。 我正在使用 Server 2016。

我的桌子:

  id  |  group_id  |  value  
------+------------+---------
   1  |         1  |    15
   2  |         1  |    16
   3  |         1  |    20
   4  |         2  |    12
   5  |         2  |    15
   6  |         3  |     8

预期输出:

 group_id  |         list
-----------+-----------------------
        1  |  '15,16,17,18,19,20'
        2  |  '12,13,14,15'
        3  |  '8'

【问题讨论】:

    标签: sql sql-server tsql sql-server-2016


    【解决方案1】:

    这是另一种方式。创建一个接受开始和结束数字并生成缺失数字的函数。

    create function dbo.get_list(@start int, @end int)
    returns varchar(1000)
    as begin
        declare @retval varchar(1000);
        set @retval = cast(@start as varchar(1000));
        set @start = @start + 1;
    
        while @start <= @end
        begin
            set @retval = @retval + ',' + cast(@start as varchar(1000));
            set @start = @start + 1;
        end;
    
        return @retval
    end
    

    完成后,编写以下 SQL:

    select group_id, dbo.get_list(min(value), max(value))
    from test
    group by group_id
    

    结果

    group_id  list
    --------  ------------------
    1         15,16,17,18,19,20
    2         12,13,14,15
    3         8
    

    【讨论】:

      【解决方案2】:

      我认为递归 CTE 是一种很好的方法:

      with t as (
            select v.*
            from (values (1, 1, 15),
                         (2, 1, 16),
                         (3, 1, 20),
                         (4, 2, 12),
                         (5, 2, 15),
                         (6, 3, 8)
                 ) v(  id, group_id, value )
           ),
           cte as (
            select t.group_id, min(t.value) as value, max(t.value) as maxvalue, convert(varchar(max), min(t.value)) as vals, 1 as lev
            from t
            group by t.group_id
            union all
            select cte.group_id, value + 1, maxvalue, concat(vals, ',', value + 1), lev + 2
            from cte
            where value < maxvalue
           )
      select cte.group_id, cte.vals
      from (select cte.*, max(cte.lev) over (partition by cte.group_id) as maxlev
            from cte
           ) cte
      where lev = maxlev
      order by group_id;
      

      Here 是一个 dbfiddle。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多