SQL生存规则实现:供应商ID映射规则编写求助
问题:基于supplierid的elig字段映射规则实现(SQL)
需求规则
- 规则1:若同一
supplierid下存在任意行elig为Cond A,则该supplierid的最终elig为Cond A - 规则2:若同一
supplierid下同时存在A和Not A(且无Cond A),则最终elig为A - 规则3:同一
supplierid下elig重复时去重保留一条
输入数据集(表名:poc_demo)
supplierid,elig,source 1,A,source1 1,Not A,source2 2,A,source1 2,Cond A,source2 3,Not A,source1 3,Cond A,source2 4,Cond A,source1 4,Cond A,source2 5,Not A,source1 5,Not A,source2
预期输出
supplierid,elig 1,A 2,Cond A 3,Cond A 4,Cond A 5,Not A
原SQL问题分析
你之前的SQL逻辑错误在于:CASE语句是针对单条记录的elig值判断,没有考虑整个supplierid分组内的所有elig集合,无法覆盖规则1和规则2的全局判断需求。
解决方案SQL
方案1:GROUP BY聚合实现
通过分组聚合直接判断每个supplierid的全局状态,一步完成规则1、2、3:
SELECT supplierid, CASE -- 优先触发规则1:分组内存在Cond A则返回Cond A WHEN MAX(CASE WHEN elig = 'Cond A' THEN 1 ELSE 0 END) = 1 THEN 'Cond A' -- 触发规则2:分组内同时有A和Not A则返回A WHEN MAX(CASE WHEN elig = 'A' THEN 1 ELSE 0 END) = 1 AND MAX(CASE WHEN elig = 'Not A' THEN 1 ELSE 0 END) = 1 THEN 'A' -- 其他情况:分组内只有单一值,直接取该值(满足规则3) ELSE MAX(elig) END AS elig FROM poc_demo GROUP BY supplierid;
方案2:窗口函数+去重实现
先通过窗口函数标记每个supplierid的状态,再通过DISTINCT去重:
WITH supplier_status AS ( SELECT supplierid, elig, -- 标记当前supplierid是否包含Cond A MAX(CASE WHEN elig = 'Cond A' THEN 1 ELSE 0 END) OVER (PARTITION BY supplierid) AS has_cond_a, -- 标记当前supplierid是否包含A MAX(CASE WHEN elig = 'A' THEN 1 ELSE 0 END) OVER (PARTITION BY supplierid) AS has_a, -- 标记当前supplierid是否包含Not A MAX(CASE WHEN elig = 'Not A' THEN 1 ELSE 0 END) OVER (PARTITION BY supplierid) AS has_not_a FROM poc_demo ) SELECT DISTINCT supplierid, CASE WHEN has_cond_a = 1 THEN 'Cond A' WHEN has_a = 1 AND has_not_a = 1 THEN 'A' ELSE elig END AS elig FROM supplier_status;
两种方案都能准确匹配你的预期输出,优先推荐方案1,逻辑更简洁,性能更优。
内容的提问来源于stack exchange,提问作者sashmi
相关产品推荐
相关产品推荐

