【问题标题】:SQL Running Total Grouped By LimitSQL 运行总数按限制分组
【发布时间】:2017-02-17 05:38:56
【问题描述】:

我正在尝试确定如何根据 Qty 列的累积总数将记录分组在一起,以使组大小不超过 50。所需的组在 group 列中给出,示例数据如下。

有没有办法在 SQL(特别是 SQL Server 2012)中实现这一点?

感谢您的帮助。

ID      Qty     Group
1       10      1
2       20      1
3       30      2  <- 60 greater than 50 so new group
4       40      3
5       2       3
6       3       3
7       10      4
8       25      4
9       15      4
10      5       5

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    您可以使用 CTE 来实现目标。

    如果其中一个项目超过50个,仍然会分配给它一个组

    DECLARE @Data TABLE (ID int identity(1,1) primary key, Qty int)
    INSERT @Data VALUES (10), (20), (30), (40), (2), (3), (10), (25), (15), (5)
    
    ;WITH cte AS
    (
        SELECT ID, Qty, 1 AS [Group], Qty AS RunningTotal FROM @Data WHERE ID = 1
        UNION ALL
        SELECT data.ID, data.Qty, 
            -- The group limits to 50 Qty
            CASE WHEN cte.RunningTotal + data.Qty > 50 THEN cte.[Group] + 1 ELSE cte.[Group] END, 
            -- Reset the running total for each new group
            data.Qty + CASE WHEN cte.RunningTotal + data.Qty > 50 THEN 0 ELSE cte.RunningTotal END
        FROM @Data data INNER JOIN cte ON data.ID = cte.ID + 1
    )
    SELECT ID, Qty, [Group] FROM cte
    

    【讨论】:

    • 此解决方案确实有效,但是如果示例数据包含更多行,则递归将超过限制。有非递归的解决方案吗?
    【解决方案2】:

    以下查询为您提供了您想要的大部分内容。结果的另一个自连接将计算组大小:

    select a.ID, G, sum(b.Qty) as Total
    from (
        select max(ID) as ID, G
        from (
            select a.ID, sum(b.Qty) / 50 as G 
            from T as a join T as b
            where a.ID >= b.ID
            group by a.ID
        ) as A
        group by G
    ) as a join T as b
    where a.ID >= b.ID
    group by a.ID
    
    ID          G           Total 
    ----------  ----------  ----------
    2           0           30        
    3           1           60        
    8           2           140       
    10          3           160       
    

    两个重要的技巧:

    1. 使用带不等式的自联接获取运行总计
    2. 使用整数除法计算组数。

    我在canonical SQL 页面上讨论了这个和其他技术。

    【讨论】:

    • 我不认为这里的组号是 OP 正在寻找的。例如。对于示例中的 ID 4 - 40,这将返回组编号为 2 ,而它应该是 3 因为一旦一个组用尽,它需要填充到 50 以便新组在填充后的总数之后开始。
    【解决方案3】:

    您需要为此创建一个存储过程。

    如果您的数据库中有 Group 列,那么您必须在插入新记录时通过获取最大 Group 值及其 Qty 列的总和来处理它,否则如果您希望 Group 列在 select 语句中计算,那么您有对存储过程进行相应的编码。

    【讨论】:

    • 这不能回答问题
    猜你喜欢
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多