私はテーブルを持っています:
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を追加して合計をオフセットします.それでも近いですが、葉巻はありません.