Oracle实现:同CREDIT_ID下SCORE_TYPE不一致时返回NULL的方法
Oracle分组统计子产品评分类型一致性实现方案
业务规则说明
- 数据实体关系:每笔信贷申请唯一标识为
CREDIT_ID,单申请下关联多个子产品,子产品唯一标识为FACIL_ID,每个子产品对应评分类型字段SCORE_TYPE - 示例数据情况:
CREDIT_ID=11111下共4个子产品,所有子产品SCORE_TYPE均为'G'CREDIT_ID=22222下共4个子产品,SCORE_TYPE取值包含'G'、'B'、'Z',存在差异
聚合需求
按CREDIT_ID分组输出,每个申请返回一行结果:
- 若申请下所有子产品
SCORE_TYPE取值完全一致,返回该评分类型值 - 若申请下
SCORE_TYPE取值存在差异,返回NULL - 预期输出:
CREDIT_ID=11111对应SCORE_TYPE='G',CREDIT_ID=22222对应SCORE_TYPE=NULL
原有写法问题
最初尝试的SQL无法得到正确结果,核心原因是分组查询语法不匹配:在GROUP BY CREDIT_ID的聚合逻辑中,SELECT子句的非分组字段必须用聚合函数包裹,直接写裸字段SCORE_TYPE会触发Oracle"不是GROUP BY表达式"的报错,即使特殊场景下不报错,返回的也是分组内随机行的取值,逻辑不符合预期。
原有错误代码:
CASE WHEN COUNT(DISTINCT SCORE_TYPE) > 1 THEN null ELSE SCORE_TYPE END AS SCORE_TYPE
正确实现脚本
兼容所有Oracle版本的通用写法
当分组内SCORE_TYPE去重计数为1时,用MAX()/MIN()聚合函数取该唯一值即可(所有值一致时,max和min返回结果完全相同):
SELECT CREDIT_ID, CASE WHEN COUNT(DISTINCT SCORE_TYPE) = 1 THEN MAX(SCORE_TYPE) ELSE NULL END AS SCORE_TYPE -- 替换为你的实际业务表名 FROM CREDIT_FACIL_TABLE GROUP BY CREDIT_ID;
Oracle 12c及以上版本简化写法
可以借助LISTAGG函数做一致性校验,逻辑等价:
SELECT CREDIT_ID, CASE WHEN LENGTH(LISTAGG(SCORE_TYPE, '') WITHIN GROUP (ORDER BY FACIL_ID)) = LENGTH(MAX(SCORE_TYPE)) THEN MAX(SCORE_TYPE) ELSE NULL END AS SCORE_TYPE -- 替换为你的实际业务表名 FROM CREDIT_FACIL_TABLE GROUP BY CREDIT_ID;
提示:如果
SCORE_TYPE字段存在NULL值,可以提前用NVL(SCORE_TYPE, '特殊空值标识')替换字段参与计算,避免空值被聚合函数忽略导致的判断偏差。
内容的提问来源于stack exchange,提问作者user2762336
相关产品推荐
相关产品推荐

