Oracle SQL如何获取首条记录Flag为N且后续转为Y的记录
解决Oracle中筛选初始Flag为N且后续转为Y的记录问题
嘿,这个需求咱们可以用Oracle的窗口函数优雅解决,核心是要判断每个RollNo分组的两个关键条件:初始Flag为N,并且分组内至少出现过一次Y。下面是具体的实现方案:
方案一:使用CTE结合窗口函数
WITH grouped_records AS ( SELECT RollNo, Name, Flag, Month, -- 获取当前RollNo分组的第一条记录的Flag(初始状态) FIRST_VALUE(Flag) OVER (PARTITION BY RollNo ORDER BY Month) AS initial_flag, -- 标记当前分组是否存在Flag为Y的记录 MAX(CASE WHEN Flag = 'Y' THEN 1 ELSE 0 END) OVER (PARTITION BY RollNo) AS has_y_flag FROM your_table -- 这里替换成你的实际表名 ) SELECT RollNo, Name, Flag, Month FROM grouped_records WHERE initial_flag = 'N' AND has_y_flag = 1 ORDER BY RollNo, Month;
逻辑解释:
- CTE
grouped_records:给每条记录额外计算两个字段:initial_flag:通过FIRST_VALUE窗口函数,按Month排序后取每个RollNo分组的第一条记录的Flag,以此确定该用户的初始状态。has_y_flag:用MAX+CASE组合,判断整个分组内是否存在Flag为Y的记录(存在则返回1,否则0)。
- 主查询筛选:只保留初始Flag为N且分组内出现过Y的记录,最后按
RollNo和Month排序,就能得到你要的结果。
方案二:先筛选符合条件的RollNo再关联原表
如果你更习惯子查询的写法,也可以先找出符合条件的RollNo列表,再和原表关联获取所有记录:
SELECT t.* FROM your_table t INNER JOIN ( SELECT DISTINCT RollNo FROM ( SELECT RollNo, FIRST_VALUE(Flag) OVER (PARTITION BY RollNo ORDER BY Month) AS initial_flag, COUNT(CASE WHEN Flag = 'Y' THEN 1 END) OVER (PARTITION BY RollNo) AS y_count FROM your_table ) WHERE initial_flag = 'N' AND y_count > 0 ) valid_rolls ON t.RollNo = valid_rolls.RollNo ORDER BY t.RollNo, Month;
验证结果:
这两个方案都会返回你预期的结果:
RollNo Name Flag Month 1 bob N Jan 1 bob N Feb 1 bob Y Mar 2 rock N Jan 2 rock Y Feb 2 rock Y Apr
而RollNo=3的记录因为初始Flag是Y,会被自动排除,完全符合需求。
内容的提问来源于stack exchange,提问作者Salva
相关产品推荐
相关产品推荐

