带条件的SQL分组

时间:2019-05-08 11:10:11

标签: sql sql-server tsql

我想对表中的行求和。该算法理论上很简单,但是当我需要建立查询时(至少对我来说)很难。

通常,我想对“子组”的“值”求和。子组定义为一系列元素,这些元素从type = 0的第一行开始,到type = 1的最后一行结束。该子组应该只包含一个类型为= 0的(第一)行。

下面的示例呈现正确(左)和错误(右)的行为。 sample

我尝试了几种方法,包括分组和分区。不幸的是,没有任何成功。有人有类似的问题吗?

我使用了MS SQL Server(因此允许使用T-SQL“魔术”)

编辑:

我想要的结果:

“ ab”,6

“ cdef”,20

“吉”,10

“ kl”,8

3 个答案:

答案 0 :(得分:1)

您可以通过累加零来确定组。然后使用聚合或窗口函数。

请注意,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);

答案 1 :(得分:1)

您可以将窗口函数与累积方法一起使用:

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;

答案 2 :(得分:0)

带有游标和输出表的解决方案。 正如戈登(Gordon)所写,尚未定义集合的排序方式,因此在此也使用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