基于分组和顺序求和

Sum Based on Grouping and Order

我有类似于下面的原始数据...

WO  OP  WC          Time
1   10  Band Saw    2.0
1   15  Band Saw    5.0
1   17  Band Saw    10.0
1   20  CNC Lathe   6.0
1   22  Band Saw    102.0
1   30  Inspection  33.0
2   10  Band Saw    1.5
2   20  CNC Lathe   6.00
2   20  CNC Lathe   2.00
2   30  CNC Punch   0.5
2   40  Manual Ops  1.25
2   50  Inspection  0.00

我需要它像下面那样求和和分组。即,在 WC 更改之前对 WO/WC 列的时间求和,而不是整个 WO 的总和。希望我已经解释清楚了(可能没有) 我们需要支持 SQL Server 2005。

WO  WC          Time
1   Band Saw    17.0
1   CNC Lathe   6.0
1   Band Saw    102.0
1   Inspection  33.0
2   Band Saw    1.5
2   CNC Lathe   8.00
2   CNC Punch   0.5
2   Manual Ops  1.25
2   Inspection  0.00

使用递归 CTE:

;WITH
    cte1 AS
    (
        SELECT  WO, OP, WC, Time,
                ROW_NUMBER() OVER (ORDER BY WO, Op) AS RowNumber
        FROM    MyTable
    ),
    cte2 AS
    (
        SELECT  WO, OP, WC, Time, RowNumber,
                1 AS GroupID
        FROM    cte1
        WHERE   RowNumber = 1
        UNION ALL
        SELECT  cte1.WO, cte1.OP, cte1.WC, cte1.Time, cte1.RowNumber,
                CASE
                    WHEN cte1.WC = cte2.WC THEN cte2.GroupID
                    ELSE cte2.GroupID + 1
                END AS GroupID
        FROM    cte1
        INNER JOIN cte2 ON cte1.RowNumber = cte2.RowNumber + 1  
    )

SELECT  WO, WC, SUM(Time) As TotalTime
FROM    cte2
GROUP BY GroupID, WO, WC
OPTION  (MAXRECURSION 0)

我没有 SQL Server 2005 可以测试,但它应该可以工作。如果您需要更多详细信息,请查询 cte1cte2.

像这样的事情呢。我在您定义的顺序(WO 和 OP)上构建了一个 row_number,然后,我在按 WO 和 OP 排序的每个 WC 上构建了另一个 row_number。现在你有两个 row_number。一个在整个集合上,一个在每个 WC 上。现在,当你从前者中减去后者时,只要只有 1 行差异,你就会形成组,每次多于一行,你就会得到一个新的分组。无需递归。

;with t (WO, OP, WC, Time) as
(
select 1,   10,  'Band Saw',    2.0
union all select 1,   15,  'Band Saw',    5.0
union all select 1,   17,  'Band Saw',    10.0
union all select 1,   20,  'CNC Lathe',   6.0
union all select 1,   22,  'Band Saw',    102.0
union all select 1,   30,  'Inspection',  33.0
union all select 2,   10,  'Band Saw',    1.5
union all select 2,   20,  'CNC Lathe',   6.00
union all select 2,   20,  'CNC Lathe',   2.00
union all select 2,   30,  'CNC Punch',   0.5
union all select 2,   40,  'Manual Ops',  1.25
union all select 2,   50,  'Inspection',  0.00
), rn as
(

    select 
        grp= row_number() over (order by WO, op) - row_number() over (partition by wo, wc order by wo, op),
        *
    from t
)
select grp, wo, wc, sum(time)
from rn
group by grp, wo, wc

编辑为使用一个 cte。还按第二顺序固定了分区。这优于 rcte 提供的数据,并且可能会更好地扩展,因为它不必递归任意次数。

感谢 Xedni 为我提供了大部分答案。我必须将 Max(op) 和排序添加到他提供的解决方案中。

;with t (WO, OP, WC, Time) as
    (
    select 1,   10,  'Band Saw',    2.0
    union all select 1,   15,  'Band Saw',    5.0
    union all select 1,   17,  'Band Saw',    10.0
    union all select 1,   20,  'CNC Lathe',   6.0
    union all select 1,   22,  'Band Saw',    102.0
    union all select 1,   30,  'Inspection',  33.0
    union all select 2,   10,  'Band Saw',    1.5
    union all select 2,   20,  'CNC Lathe',   6.00
    union all select 2,   20,  'CNC Lathe',   2.00
    union all select 2,   30,  'CNC Punch',   0.5
    union all select 2,   40,  'Manual Ops',  1.25
    union all select 2,   50,  'Inspection',  0.00
    ), rn as
    (

        select 
            grp= row_number() over (order by WO, op) - row_number() over (partition by wo, wc order by wo, op),
            *
        from t
    )
    select grp, wo, MAX(op) AS MaxOp, wc, sum(time)
    from rn
    group by grp, wo, wc
    ORDER BY wo, MaxOp