Группировка SQL с условием - PullRequest
0 голосов
/ 08 мая 2019

Я хочу суммировать строки в таблице. Алгоритм довольно прост в теории, но сложен (по крайней мере для меня), когда мне нужно построить запрос.

Как правило, я хочу суммировать «значения» «подгруппы». Подгруппа определяется как диапазон элементов, начиная с первой строки, где type = 0, и заканчивая последней строкой, где type = 1. подгруппа должна содержать только одну (первую) строку с типом = 0.

Пример ниже представляет правильное (слева) и неправильное (справа) поведение. sample

Я пробовал несколько подходов, включая группирование и разбиение. К сожалению, без какого-либо успеха. У кого-нибудь была похожая проблема?

Я использовал MS SQL Server (поэтому «волшебство» T-SQL разрешено)

EDIT:

Результаты, которые я хочу:

"б", 6

"CDEF", 20

"ГХИ", 10

"Ы", 8

Ответы [ 3 ]

1 голос
/ 08 мая 2019

Вы можете использовать оконную функцию с кумулятивным подходом:

select t.*, sum(value) over (partition by grp)
from (select t.*, sum(case when type = 0 then 1 else 0 end) over (order by id) as grp
      from table t
     ) t
where grp > 0;
1 голос
/ 08 мая 2019

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

Обратите внимание, что таблицы SQL представляют неупорядоченные наборы, поэтому вам необходим столбец для указания порядка. Код ниже предполагает, что этот столбец id.

select min(id), max(id), sum(value)
from (select t.*,
             sum(case when type = 0 then 1 else 0 end) over (order by id) as grp
      from t
     ) t
group by grp
order by min(id);
0 голосов
/ 08 мая 2019

Решение с курсором и выходной таблицей. Как писал Гордон, не определено, как будет упорядочен набор, поэтому здесь также используется ID.

declare @output as table (
    ID_sum nvarchar(max)
    ,value_sum int
)

DECLARE @ID as nvarchar(1)
    ,@value as int
    ,@type as int
    ,@ID_sum as nvarchar(max)
    ,@value_sum as int
    ,@last_type as int

DECLARE group_cursor CURSOR FOR
    SELECT [ID],[value],[type]
    FROM [t]
    ORDER BY ID

OPEN group_cursor

FETCH NEXT FROM group_cursor   
INTO @ID, @value,@type

WHILE @@FETCH_STATUS = 0  
BEGIN  
    if (@last_type is null and @type = 0)
    begin
        set @ID_sum = @ID
        set @value_sum = @value
    end

    if (@last_type in(0,1) and @type = 1)
    begin
        set @ID_sum += @ID
        set @value_sum += @value
    end

    if (@last_type = 1 and @type = 0)
    begin
        insert into @output values (@ID_sum, @value_sum)        
        set @ID_sum = @ID
        set @value_sum = @value
    end

    if (@last_type = 0 and @type = 0)
    begin
        set @ID_sum = @ID
        set @value_sum = @value
    end

    set @last_type = @type
    FETCH NEXT FROM group_cursor   
    INTO @ID, @value,@type
END   
CLOSE group_cursor;  
DEALLOCATE group_cursor;  

if (@last_type = 1)
begin
    insert into @output values (@ID_sum, @value_sum)        
end

select *
from @output
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...