Как выбрать несколько диапазонов, разделенных идентификатором группы - PullRequest
0 голосов
/ 25 апреля 2019

Мне нужно создать список значений через запятую для каждого идентификатора группы в таблице и заполнить все пропущенные значения, но я не совсем уверен, как поступить. Я использую 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'

Ответы [ 2 ]

0 голосов
/ 25 апреля 2019

Я думаю, что рекурсивный 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;

Здесь - это db <> скрипка.

0 голосов
/ 25 апреля 2019

Вот альтернативный способ. Создайте функцию, которая принимает начальные и конечные числа и генерирует пропущенные числа.

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
...