如何用SQL计算产品最近归属对应团队的累计停留天数?
解决方案:计算产品最近团队归属的分段总天数
要解决你的需求,关键是先识别出连续归属同一团队的记录分组,再针对这些分组提取你需要的统计值。下面以你提供的示例数据为例,给出适用于主流SQL数据库(如MySQL 8+、PostgreSQL、SQL Server)的实现方案:
步骤1:标记连续团队分组
首先,我们需要给每条记录打上"连续团队分组ID"——当当前记录的团队和上一条不同时,分组ID递增,这样同一连续团队的所有记录会共享同一个分组ID。
步骤2:计算每个分组的总天数并排序
接下来,按分组ID聚合,计算每个分组的总天数,同时给分组按时间倒序排序(最新的分组排第1位)。
完整SQL代码
假设你的表名为product_status,字段对应示例中的product_id, date, status, days_in_status, team,可以用CTE(公共表表达式)分步实现:
WITH grouped_status AS ( SELECT product_id, date, team, days_in_status, -- 生成连续团队分组ID:当前团队与上一行不同时,分组ID+1 SUM(CASE WHEN LAG(team) OVER (PARTITION BY product_id ORDER BY date) != team THEN 1 ELSE 0 END) OVER (PARTITION BY product_id ORDER BY date) AS group_id FROM product_status -- 可选:如果只需要单个产品,添加WHERE product_id = '1a' ), group_totals AS ( SELECT product_id, team, SUM(days_in_status) AS total_days, -- 按分组的最新日期倒序排序,最新分组rank=1 ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY MAX(date) DESC) AS group_rank FROM grouped_status GROUP BY product_id, group_id, team ) -- 提取目标结果 SELECT product_id, -- 最近一次QA团队的总天数 MAX(CASE WHEN team = 'QA' AND group_rank = 1 THEN total_days END) AS latest_qa_total, -- 最近一次QA之前的Engineering团队总天数 MAX(CASE WHEN team = 'engineering' AND group_rank = 2 THEN total_days END) AS prev_engineering_total FROM group_totals GROUP BY product_id;
代码说明
grouped_statusCTE:- 使用
LAG(team)窗口函数获取当前记录的上一条记录的团队名称。 - 通过
SUM(...) OVER()累计分组标识,确保同一连续团队的记录拥有相同的group_id。
- 使用
group_totalsCTE:- 按
product_id、group_id、team分组,计算每个连续团队段的总天数total_days。 - 使用
ROW_NUMBER()给分组按时间倒序排名,最新的分组(最近的团队段)group_rank为1,上一个分组为2,以此类推。
- 按
最终查询:
- 用
CASE语句筛选出group_rank=1的QA分组总天数,以及group_rank=2的Engineering分组总天数,得到你需要的结果。
- 用
适配你的示例数据
针对你第二个示例的输入,执行这段SQL后会返回:
| product_id | latest_qa_total | prev_engineering_total |
|---|---|---|
| 1a | 2 | 4 |
完全符合你需要的1+1和1+3的结果。
内容的提问来源于stack exchange,提问作者LAMPORT




