我有桌子:
PersonID FirstName PersonAge
1 Pras 2
2 Deep 3
3 Test 4
4 Prash 2
5 ser 1
6 df 8
7 ddf 5
8 vvv 4
9 ddd 1
10 eww 6
11 vvv 3
12 vbbb 7
13 Prabbbbs 6
我想对它们进行分组,使组的总年龄不超过 10 岁。
我可以通过递归来做到这一点,但在较大的表上效率低下。
;WITH cte AS
(
SELECT PersonID, PersonAge, 1 AS [Group], PersonAge AS RunningTotal FROM POP where PersonId=1
UNION ALL
SELECT data.PersonId, data.PersonAge,
CASE WHEN cte.RunningTotal + data.PersonAge > 10 THEN cte.[Group] + 1 ELSE cte.[Group] END,
-- Reset the running total for each new group
data.PersonAge + CASE WHEN cte.RunningTotal + data.PersonAge > 10 THEN 0 ELSE cte.RunningTotal END
FROM POP data INNER JOIN cte ON data.PersonId = cte.PersonID + 1
)
SELECT * FROM cte
所以,我需要的输出将是:
PersonID PersonAge Group RunningTotal
1 2 1 2
2 3 1 5
3 4 1 9
4 2 2 2
5 1 2 3
6 8 3 8
7 5 4 5
8 4 4 9
9 1 4 10
10 6 5 6
11 3 5 9
12 7 6 7
13 6 7 6
有没有好的非递归解决方案?
编辑:试验#1:按照运行总计的思路思考,我得到了一张包含 CurrRunningTotal 和 RunningTotal 的表格,直到上一行。
WITH TE
AS (SELECT
PersonId,
FirstName,
PersonAge,
SUM(PersonAge) OVER (ORDER BY PersonId
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
AS PrevRunningTotal,
SUM(PersonAge) OVER (ORDER BY PersonId
ROWS UNBOUNDED PRECEDING)
AS RunningTotal
FROM POP),
MergedGroup
AS (SELECT
*,
SUM(CASE
WHEN RunningTotal > @total THEN RunningTotal - @total
ELSE PersonAge
END) OVER (ORDER BY PersonId) AS Total
FROM TE)
SELECT
*
FROM MergedGroup
我觉得使用 PreviousRunningTotal 当我的阈值被满足时我可以做一些魔法来获得一个带有填充的总数,即当阈值被超过时,将 10 添加到当前行以抵消总数。仍然接近但没有雪茄。