关联含唯一ID的T1与多Code的T2并生成标签列的SQL问题
解决T1关联T2后ID重复的SQL方案
问题根源
T2中一个ID对应多个Code值,直接关联T1(ID唯一)会因为T2的多行数据导致T1的ID被重复输出、行数膨胀。核心是要先对T2按ID做存在性判断/聚合,再和T1关联,保证每个ID只返回一次。
方案一:聚合T2后关联(最直观)
先对T2按ID分组,标记每个ID是否包含目标Code(002/004),再关联T1:
SELECT t1.*, CASE WHEN t2.has_target_code = 'Y' THEN 'DISCHARGED' ELSE 'OTHER' END AS Label FROM T1 t1 LEFT JOIN ( SELECT ID, -- 只要有一个Code符合条件,就返回Y MAX(CASE WHEN Code IN ('002', '004') THEN 'Y' ELSE 'N' END) AS has_target_code FROM T2 GROUP BY ID ) t2 ON t1.ID = t2.ID;
- 子查询通过
MAX函数聚合:只要ID下存在002/004,has_target_code就为Y,否则为N - 关联后T1的每条记录只会匹配一行,彻底解决ID重复问题
方案二:用EXISTS做存在性判断(性能更优)
不需要提前聚合T2,直接通过EXISTS判断当前ID是否在T2中有匹配的Code:
SELECT t1.*, CASE WHEN EXISTS ( SELECT 1 FROM T2 t2 WHERE t2.ID = t1.ID AND t2.Code IN ('002', '004') ) THEN 'DISCHARGED' ELSE 'OTHER' END AS Label FROM T1 t1;
EXISTS只做存在性检查,找到匹配项就停止检索,性能比聚合更高效(尤其当T2的ID+Code有索引时)- 天然保证T1的每条记录只返回一次,不会产生重复行
方案三:窗口函数标记(需保留T2其他字段时用)
如果需要同时展示T2的部分字段,但又要避免ID重复,可以用窗口函数优先选取符合条件的记录:
WITH t2_flagged AS ( SELECT ID, Code, CASE WHEN Code IN ('002', '004') THEN 'DISCHARGED' ELSE 'OTHER' END AS temp_label, -- 把符合条件的Code排在最前面,取第一条 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY CASE WHEN Code IN ('002', '004') THEN 1 ELSE 2 END) AS rn FROM T2 ) SELECT t1.*, COALESCE(t2.temp_label, 'OTHER') AS Label FROM T1 t1 LEFT JOIN t2_flagged t2 ON t1.ID = t2.ID AND t2.rn = 1;
- 按ID分区,给符合条件的记录标记
rn=1,关联时只取这一行,既保留T2信息,又避免重复
内容的提问来源于stack exchange,提问作者Gingerhaze
相关产品推荐
相关产品推荐

