检测并设置行间列值:为PRD_SLD表添加STRT与END列
搞定PRD_SLD表的连续状态起止日期计算
嘿,我明白你要做的是给每一行数据标记它所在的SALE_IND连续状态的起止日期,对吧?先把你的需求理清楚:
原始表数据
| ID | DATE | SALE_IND |
|---|---|---|
| 3 | 2012 | 0 |
| 3 | 2013 | 0 |
| 3 | 2014 | 1 |
| 3 | 2014 | 1 |
| 3 | 2015 | 1 |
| 3 | 2016 | 0 |
| 3 | 2017 | 1 |
你想要的最终结果
每个行都对应它所属的连续SALE_IND状态的开始和结束日期:
| ID | DATE | SALE_IND | STRT | END |
|---|---|---|---|---|
| 3 | 2012 | 0 | 2012 | 2014 |
| 3 | 2013 | 0 | 2012 | 2014 |
| 3 | 2014 | 1 | 2014 | 2016 |
| 3 | 2014 | 1 | 2014 | 2016 |
| 3 | 2015 | 1 | 2014 | 2016 |
| 3 | 2016 | 0 | 2016 | 2017 |
| 3 | 2017 | 1 | 2017 | 2017 |
你已经有的基础
你说已经有个能正常运行的CTE,可以抓出SALE_IND变化的关键行,返回的结果大概是这样的(我补全了没写完的部分):
| ID | DATE | SALE_IND |
|---|---|---|
| 3 | 2012 | 0 |
| 3 | 2014 | 1 |
| 3 | 2016 | 0 |
| 3 | 2017 | 1 |
接下来的解决方案:基于你的CTE生成区间
假设你那个抓变化点的CTE名叫ChangePoints,我给你写个完整的SQL,直接就能得到你要的结果:
WITH ChangePoints AS ( -- 把你已有的CTE代码直接放到这里就行 SELECT ID, DATE, SALE_IND FROM PRD_SLD WHERE -- 这里是你判断状态变化的逻辑,不用改 ), -- 给每个变化点配上对应的区间结束日期 ChangeRanges AS ( SELECT ID, DATE AS StartDate, SALE_IND, -- 用LEAD取下一个变化点的日期,没有的话就用当前日期(最后一个状态) LEAD(DATE, 1, DATE) OVER (PARTITION BY ID ORDER BY DATE) AS EndDate FROM ChangePoints ) -- 把原始表和区间表关联,匹配每一行所属的区间 SELECT p.ID, p.DATE, p.SALE_IND, r.StartDate AS STRT, r.EndDate AS END FROM PRD_SLD p JOIN ChangeRanges r ON p.ID = r.ID AND p.SALE_IND = r.SALE_IND AND p.DATE >= r.StartDate AND p.DATE < r.EndDate -- 单独处理最后一个状态(起止日期相同的情况) UNION ALL SELECT p.ID, p.DATE, p.SALE_IND, r.StartDate AS STRT, r.EndDate AS END FROM PRD_SLD p JOIN ChangeRanges r ON p.ID = r.ID AND p.SALE_IND = r.SALE_IND AND p.DATE = r.StartDate AND r.StartDate = r.EndDate ORDER BY p.ID, p.DATE;
简单说下逻辑
- ChangeRanges这个CTE:用
LEAD()窗口函数,给每个变化点找下一个变化的日期,这个日期就是当前状态的结束日期;如果是最后一个状态,就用自己的日期当结束日期。 - 关联匹配:把原始表的每一行,和对应的状态区间做关联,确保日期落在区间里。
- 边界处理:最后一个状态的起止日期是一样的,单独写个
UNION ALL来匹配这种情况,避免漏行。
这个方案完全基于你已经有的CTE,直接替换进去就能用,肯定能得到你想要的结果!
内容的提问来源于stack exchange,提问作者dragonfromdreams
相关产品推荐
相关产品推荐

