SQL Server:利用ROW_NUMBER与CASE语句筛选指定子表数据行
我来帮你完善这个查询,确保满足所有三个筛选条件,同时正确处理重复ID的去重逻辑。咱们一步步拆解需求,再调整SQL语句:
核心需求回顾
首先明确要实现的逻辑:
- 先筛选子表中
Inactivated_On非空的行,按Id分组后取Updated_on最新的一行(降序TOP1) - 结合父表数据,满足以下规则:
- Case1:若当前行对应的父表
Type_Id=2,则其父节点对应的子表行Inactivated_On必须为NULL - Case2:若当前行对应的父表
Type_Id=1,则其父节点对应的子表行Inactivated_On为NULL,且该行Ans不等于'false' - Case3:子行与父行
Inactivated_On均为NULL的行直接排除(已通过第一步筛选子行非空覆盖)
- Case1:若当前行对应的父表
完善后的查询语句
WITH RankedChild AS ( -- 第一步:筛选子表中Inactivated_On非空的目标行,按Id分组并按Updated_on降序排名 SELECT Id, Cust_id, Item_Id, Inactivated_On, Updated_on, Ans, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Updated_on DESC) AS RN FROM CHILD_TBL WHERE Inactivated_On IS NOT NULL AND Cust_id = 123 AND Item_Id = 541 ), UniqueChild AS ( -- 第二步:取每个Id的最新一行(去重) SELECT Id, Cust_id, Item_Id, Inactivated_On, Updated_on, Ans FROM RankedChild WHERE RN = 1 ) -- 第三步:关联父表和父行数据,应用Case筛选条件 SELECT uc.* FROM UniqueChild uc JOIN PARENT_TBL pt ON uc.Id = pt.Id LEFT JOIN UniqueChild parent_uc ON pt.Parent_Id = parent_uc.Id WHERE -- 匹配Case1:Type_Id=2时,父行Inactivated_On必须为NULL (pt.Type_Id = 2 AND parent_uc.Inactivated_On IS NULL) OR -- 匹配Case2:Type_Id=1时,父行Inactivated_On为NULL且Ans≠'false' (pt.Type_Id = 1 AND parent_uc.Inactivated_On IS NULL AND parent_uc.Ans != 'false') ;
语句解释
- RankedChild CTE:先过滤出符合基础条件(
Inactivated_On非空、指定客户和商品)的子表行,用ROW_NUMBER()给每个Id的行按更新时间降序排名,确保每个Id只保留最新的一条记录。 - UniqueChild CTE:提取排名为1的行,完成去重操作。
- 关联与筛选:
- 通过
PARENT_TBL找到当前子行对应的父节点ID - 再次关联
UniqueChild获取父节点对应的子表行数据 - 用
WHERE子句分别实现Case1和Case2的逻辑,不符合条件的行会被自动排除,同时Case3的逻辑也因为第一步已经过滤了子行Inactivated_On非空而得到满足。
- 通过
验证预期结果
执行这个查询后,会得到你想要的结果:
| Id | Cust_id | Item_Id | Inactivated_On | Updated_on | Ans |
|---|---|---|---|---|---|
| 12 | 123 | 541 | 2014-05-18 08:44:00 | 2014-05-18 08:44:00 | NULL |
| 13 | 123 | 541 | 2014-05-18 08:44:00 | 2014-05-18 08:44:00 | false |
- 行12:父表
Type_Id=2,父行(Id=11)的Inactivated_On为NULL,符合Case1 - 行13:父表
Type_Id=1,父行(Id=11)的Inactivated_On为NULL且Ans≠'false',符合Case2 - 行16和7因为不满足父行条件,会被正确排除
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

