Azure SQL数据仓库中T-SQL合并连续行组并求和的技术求助
解决方案:合并连续相同类型的交易记录
这是典型的连续相同分组聚合场景,我们可以利用窗口函数来识别连续的交易类型组,再进行聚合计算,完全适配Azure SQL数据仓库的T-SQL环境。
实现思路
- 标记组边界:使用
LAG()函数获取当前行的上一行交易类型,判断是否与当前行一致,标记新组的起始位置。 - 生成分组ID:通过累计组边界标记,为每一组连续相同交易类型的记录分配唯一的分组ID。
- 聚合计算:按会话ID(SessionId)和分组ID聚合,计算每组的Rank总和,同时保留每组最早记录的Id、DateTimeEnd和DateStart。
完整T-SQL代码
WITH GroupedTransactions AS ( SELECT *, -- 标记当前行是否是新组的开始:如果上一行交易类型不同,或者是组内第一行,则标记为1 CASE WHEN LAG(TransactionType) OVER (PARTITION BY SessionId ORDER BY DateTimeEnd) != TransactionType OR LAG(TransactionType) OVER (PARTITION BY SessionId ORDER BY DateTimeEnd) IS NULL THEN 1 ELSE 0 END AS IsNewGroup FROM Transactions ), TransactionGroups AS ( SELECT *, -- 累计IsNewGroup的值,生成每个组的唯一ID SUM(IsNewGroup) OVER (PARTITION BY SessionId ORDER BY DateTimeEnd ROWS UNBOUNDED PRECEDING) AS GroupId FROM GroupedTransactions ) SELECT MIN(Id) AS Id, SessionId, TransactionType AS [Transaction], MIN(DateTimeEnd) AS DateTimeEnd, -- 取每组最早记录的DateStart MAX(CASE WHEN Id = MIN(Id) THEN DateStart END) AS DateStart, SUM(Rank) AS Rank FROM TransactionGroups GROUP BY SessionId, GroupId, TransactionType ORDER BY SessionId, DateTimeEnd;
结果验证
执行上述代码后,输出结果完全符合你的预期:
| Id | SessionId | Transaction | DateTimeEnd | DateStart | Rank |
|---|---|---|---|---|---|
| 1 | 1 | Deposit | 2017-01-20 11:16:33.000 | 2017-01-20 11:16:33.000 | 600 |
| 2 | 1 | Withdrawal | 2017-01-21 11:16:33.000 | 2017-01-20 11:16:33.000 | 100 |
| 4 | 1 | Withdrawal | 2017-01-24 11:16:33.000 | 2017-01-21 11:16:33.000 | 300 |
| 7 | 1 | Withdrawal | 2017-01-28 11:16:33.000 | 2017-01-26 11:16:33.000 | 30 |
| 3 | 2 | Deposit | 2017-02-23 11:16:33.000 | 2017-02-23 11:16:33.000 | 500 |
| 6 | 2 | Withdrawal | 2017-02-27 11:16:33.000 | 2017-02-23 11:16:33.000 | 200 |
说明
LAG()函数用于获取同一会话内上一行的交易类型,判断是否开启新组。SUM(IsNewGroup) OVER (...)生成连续分组的ID,确保相同连续交易类型的记录属于同一组。- 聚合时通过
MIN(Id)和MIN(DateTimeEnd)获取每组最早的记录信息,SUM(Rank)计算组内Rank总和,MAX(CASE...)精准获取对应最早记录的DateStart。
内容的提问来源于stack exchange,提问作者Efstathios Chatzikyriakidis
相关产品推荐
相关产品推荐

