基于分组和顺序求和
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 可以测试,但它应该可以工作。如果您需要更多详细信息,请查询 cte1
和 cte2
.
像这样的事情呢。我在您定义的顺序(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
我有类似于下面的原始数据...
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 可以测试,但它应该可以工作。如果您需要更多详细信息,请查询 cte1
和 cte2
.
像这样的事情呢。我在您定义的顺序(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