使用窗口函数为Oracle表列中重复值长链编号
Oracle中为重复值连续链编号的SQL改写
原PostgreSQL语句通过窗口函数为连续重复的列值生成分组编号,要适配Oracle数据库,需要调整两个关键语法点:
- Oracle不支持PostgreSQL的
FILTER子句,需用CASE表达式配合聚合函数实现条件计数 - Oracle没有
IS DISTINCT FROM运算符,需用NULL-safe的比较逻辑替代
改写后的Oracle兼容SQL
SELECT id, col, COUNT(CASE WHEN (col != lag_col) OR (col IS NULL AND lag_col IS NOT NULL) OR (col IS NOT NULL AND lag_col IS NULL) THEN 1 END) OVER(ORDER BY id) grp FROM ( SELECT t.*, LAG(col) OVER(ORDER BY id) AS lag_col FROM mytable t ) t ORDER BY id;
简化写法(针对非特殊值场景)
如果col列不会出现CHR(0)(ASCII空字符)这类特殊值,也可以用NVL函数简化NULL比较逻辑:
SELECT id, col, COUNT(CASE WHEN NVL(col, CHR(0)) != NVL(lag_col, CHR(0)) THEN 1 END) OVER(ORDER BY id) grp FROM ( SELECT t.*, LAG(col) OVER(ORDER BY id) AS lag_col FROM mytable t ) t ORDER BY id;
逻辑说明
- 内层查询用
LAG(col) OVER(ORDER BY id)获取当前行的上一行col值 - 外层通过
COUNT(CASE ...)统计当前行与上一行值不同(包括一方为NULL的情况)的次数,这个累计计数就是连续重复值链的分组编号
内容的提问来源于stack exchange,提问作者Wouter
相关产品推荐
相关产品推荐

