使用Join关联表后出现重复数据,求正确SQL查询语句
解决LEFT JOIN后重复数据且DISTINCT无效的SQL问题
问题背景
现有两张表Table A和Table B:
- Table A中StatusID为202的CallID字段为空
- 通过ContactID字段关联后返回重复数据,使用DISTINCT关键字去重无效
- 期望得到无重复的指定结果集
表数据
Table A:
| StatusID | CallID | ContactID |
|---|---|---|
| 202 | 65490 | |
| 302 | 1029-2134 | 65490 |
Table B:
| DateTime | SessionID | ContactID |
|---|---|---|
| 2023-05-15 02:29 | 0341-3124 | 65490 |
| 2023-05-15 02:30 | 1029-2134 | 65490 |
当前问题
仅用ContactID关联后得到4条重复数据(两条目标结果各重复一次),使用DISTINCT未解决问题,已尝试的SQL:
SELECT DISTINCT ContactID, CallID, StatusID, DateTime, SessionID from TableA A JOIN TableB B ON A.ContactID = B.ContactID
期望结果
| ContactID | CallID | StatusID | DateTime | SessionID |
|---|---|---|---|---|
| 65490 | 202 | 2023-05-15 02:29 | 0341-3124 | |
| 65490 | 1029-2134 | 302 | 2023-05-15 02:30 | 1029-2134 |
原因分析
仅通过ContactID关联时,Table A的每一行都会与Table B中所有同ContactID的行匹配,生成2*2=4条数据。而你的场景需要更精准的匹配逻辑:
- Table A中StatusID=302的行,其CallID与Table B的SessionID一致,应匹配对应行
- Table A中StatusID=202的行,CallID为空,应匹配Table B中SessionID不等于上述CallID的行
解决方案
方案1:优化关联条件
通过精准匹配CallID和SessionID,同时处理空值场景:
SELECT A.ContactID, A.CallID, A.StatusID, B.DateTime, B.SessionID FROM TableA A LEFT JOIN TableB B ON A.ContactID = B.ContactID AND ( A.CallID = B.SessionID OR (A.CallID IS NULL AND B.SessionID NOT IN (SELECT CallID FROM TableA WHERE ContactID = A.ContactID AND CallID IS NOT NULL)) ) WHERE B.DateTime IS NOT NULL; -- 过滤未匹配的空行(按需使用)
方案2:使用窗口函数去重
如果无法确定精准关联条件,可通过窗口函数对重复分组行去重:
SELECT ContactID, CallID, StatusID, DateTime, SessionID FROM ( SELECT A.ContactID, A.CallID, A.StatusID, B.DateTime, B.SessionID, ROW_NUMBER() OVER (PARTITION BY A.StatusID, A.CallID ORDER BY B.DateTime) AS rn FROM TableA A LEFT JOIN TableB B ON A.ContactID = B.ContactID ) t WHERE rn = 1;
该查询按StatusID和CallID分组,每组仅保留第一行数据,从而得到无重复的结果集。
内容的提问来源于stack exchange,提问作者Yan Aditiya
相关产品推荐
相关产品推荐

