如何通过多种方式实现获取当前行COL_C为空且前一行存在值的LAG函数查询结果
解决方法:获取目标记录的几种SQL实现
我明白你的问题了——你现在用LAG函数想抓取那些COL_A='18-AUG-2022'、当前行COL_C为空,但同COL_B分组里按COL_A排序的前一行COL_C有值的记录,但现有SQL没筛选出这些目标数据。下面给你几种不同的实现方法,你可以根据自己的数据库环境选合适的:
方法1:直接修改CTE的查询条件(最直观)
这是对你现有SQL的最小修改,直接在最终查询的WHERE子句里加上两个关键判断:当前行COL_C为空,同时前一行的PREV_COL_C不为空。
WITH DATA AS ( SELECT COL_A , COL_B , COL_C , LAG(COL_C) OVER (PARTITION BY COL_B ORDER BY COL_A) PREV_COL_C FROM TABLE_COL ) SELECT * FROM DATA WHERE COL_A = '18-AUG-2022' AND COL_C IS NULL AND PREV_COL_C IS NOT NULL;
方法2:省去CTE,直接在主查询中使用窗口函数
如果你的数据库支持在WHERE子句中直接使用窗口函数(比如PostgreSQL 12+、SQL Server 2012+、Oracle 12c+等),可以简化代码,不用CTE直接过滤:
SELECT COL_A, COL_B, COL_C, LAG(COL_C) OVER (PARTITION BY COL_B ORDER BY COL_A) PREV_COL_C FROM TABLE_COL WHERE COL_A = '18-AUG-2022' AND COL_C IS NULL AND LAG(COL_C) OVER (PARTITION BY COL_B ORDER BY COL_A) IS NOT NULL;
注意:部分老版本数据库(比如MySQL 8.0之前)不支持窗口函数出现在WHERE子句中,这种情况还是用方法1更稳妥。
方法3:用自连接替代窗口函数(兼容老版本数据库)
如果你的数据库不支持窗口函数,比如一些老版本的MySQL、SQLite,那可以用自连接的方式模拟LAG的逻辑:
SELECT t1.COL_A, t1.COL_B, t1.COL_C, t2.COL_C AS PREV_COL_C FROM TABLE_COL t1 JOIN TABLE_COL t2 ON t1.COL_B = t2.COL_B AND t2.COL_A = (SELECT MAX(COL_A) FROM TABLE_COL WHERE COL_B = t1.COL_B AND COL_A < t1.COL_A) WHERE t1.COL_A = '18-AUG-2022' AND t1.COL_C IS NULL AND t2.COL_C IS NOT NULL;
这里通过子查询找到同一COL_B分组中,COL_A比当前行小的最大值(也就是排序后的前一行),再筛选出符合条件的记录。这种方法兼容性强,但数据量大时性能可能不如窗口函数。
方法4:用LEAD函数反向验证(可选思路)
如果你想换个角度验证结果,或者需要反向逻辑的查询,可以用LEAD函数从后往前推导:
WITH DATA AS ( SELECT COL_A, COL_B, COL_C, LEAD(COL_A) OVER (PARTITION BY COL_B ORDER BY COL_A) NEXT_COL_A, LEAD(COL_C) OVER (PARTITION BY COL_B ORDER BY COL_A) NEXT_COL_C FROM TABLE_COL ) SELECT NEXT_COL_A AS COL_A, COL_B, NEXT_COL_C AS COL_C, COL_C AS PREV_COL_C FROM DATA WHERE NEXT_COL_A = '18-AUG-2022' AND NEXT_COL_C IS NULL AND COL_C IS NOT NULL;
这个思路是找“下一行是目标日期且COL_C为空,当前行COL_C不为空”的记录,然后把下一行的信息作为结果返回,和前面的方法结果完全一致,适合你需要交叉验证的时候用。
内容的提问来源于stack exchange,提问作者sharan jain
相关产品推荐
相关产品推荐

