如何编写SQL查询从含重复值的两张表中获取指定合并结果(避免重复值)
解决重复表连接后得到预期结果的SQL方案
嘿,我懂你遇到的问题了——直接用普通JOIN的话,因为两张表在Col1和Col2上存在重复值,会触发笛卡尔积,导致结果出现多余的重复行。要实现你想要的一一对应结果,我们可以借助窗口函数给每组重复记录打上行号标记,再通过行号来精准匹配数据,具体方案如下:
核心思路
给TAB1和TAB2中相同Col1+Col2组合的记录,按照你预期的匹配顺序生成行号,然后通过Col1、Col2和行号这三个条件来连接两张表,这样就能避免笛卡尔积,得到一对一的对应结果。
具体SQL代码(支持CTE的数据库,如MySQL 8+、PostgreSQL、SQL Server等)
WITH tab1_ranked AS ( SELECT Col1, Col2, Col3, Col4, -- 按Col1、Col2分组,每组内按Col4排序生成行号 ROW_NUMBER() OVER (PARTITION BY Col1, Col2 ORDER BY Col4) AS row_num FROM TAB1 ), tab2_ranked AS ( SELECT Col1, Col2, Col3, Col4, -- 按Col1、Col2分组,每组内按Col3排序生成行号(匹配你预期的AB1顺序) ROW_NUMBER() OVER (PARTITION BY Col1, Col2 ORDER BY Col3) AS row_num FROM TAB2 ) SELECT t1.Col1, t1.Col2, -- 匹配预期结果的Col3:第一行取TAB1的AA1,第二行取TAB2的AB1 CASE t1.row_num WHEN 1 THEN t1.Col3 ELSE t2.Col3 END AS Col3, t1.Col4, t2.Col4 AS Col5 FROM tab1_ranked t1 INNER JOIN tab2_ranked t2 ON t1.Col1 = t2.Col1 AND t1.Col2 = t2.Col2 AND t1.row_num = t2.row_num;
代码说明
PARTITION BY Col1, Col2:把数据按Col1和Col2的组合分成不同的组,每组内独立生成行号ORDER BY:指定每组内记录的排序规则,确保行号的生成顺序和你想要的匹配关系一致(你可以根据实际数据调整排序字段,比如如果Col4的顺序不是G1、G2,就换其他字段)- 最后通过
Col1、Col2和row_num连接,让两张表中每组的第1行对应第1行,第2行对应第2行,完美避免重复行
兼容旧版本数据库的写法(不用CTE,用子查询)
如果你的数据库不支持CTE(比如MySQL 5.x),可以换成子查询的形式,原理完全一样:
SELECT t1.Col1, t1.Col2, CASE t1.row_num WHEN 1 THEN t1.Col3 ELSE t2.Col3 END AS Col3, t1.Col4, t2.Col4 AS Col5 FROM ( SELECT Col1, Col2, Col3, Col4, ROW_NUMBER() OVER (PARTITION BY Col1, Col2 ORDER BY Col4) AS row_num FROM TAB1 ) t1 INNER JOIN ( SELECT Col1, Col2, Col3, Col4, ROW_NUMBER() OVER (PARTITION BY Col1, Col2 ORDER BY Col3) AS row_num FROM TAB2 ) t2 ON t1.Col1 = t2.Col1 AND t1.Col2 = t2.Col2 AND t1.row_num = t2.row_num;
执行这段代码后,就能得到你想要的预期结果啦!
内容的提问来源于stack exchange,提问作者Jaic E V
相关产品推荐
相关产品推荐

