T-SQL JOIN / WHERE IN返回不同的结果

时间:2016-06-28 07:16:14

标签: sql sql-server join

我有一个查询,我正在尽力优化,如果我可以使用连接而不是当前的连接(一个WHERE IN),它会帮助我很多。

目前,我的查询是:

SELECT  
cus.*
, com.COM_ID
, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
LEFT JOIN otherthing.dbo.TBL_COMMUNICATION com 
ON com.REC_ID = cus.REC_ID 
AND com.RUN_ID = cus.RUN_ID 
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
ON cha.CHA_ID = com.CHA_ID 
WHERE com.COM_ID in (
    SELECT eve.COM_ID 
    FROM otherthing.dbo.TBL_EVENT eve)

我正在尝试通过加入TBL_EVENT而不是WHERE IN来优化它(我相信我读它们的运行方式相同,但我也想选择一些TBL_EVENT列,所以加入会很好) 。我的新查询是这样的:

SELECT  
cus.*
, com.COM_ID
, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
LEFT JOIN otherthing.dbo.TBL_COMMUNICATION com 
ON com.REC_ID = cus.REC_ID 
AND com.RUN_ID = cus.RUN_ID 
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
ON cha.CHA_ID = com.CHA_ID 
INNER JOIN otherthing.dbo.TBL_EVENT eve
ON com.COM_ID = eve.COM_ID 

我认为使用内部联接意味着它只返回TBL_COMMUNICATION和TBL_EVENT中的结果。 这就是事情变得怪异的地方。

原始查询(在顶部)返回~200,000条记录。我的新查询返回约1,100,000条记录。但从我的角度来看,他们是同一个查询,所以我不确定我做错了什么。我已将INNER JOIN移动到其他左连接之上的TBL_EVENT,但它似乎没有什么区别。

任何人都可以通过加入TBL_EVENT来告诉我应该做些什么来返回相同的数据?

3 个答案:

答案 0 :(得分:2)

他们不一样

WHERE com.COM_ID in (
   SELECT eve.COM_ID 
   FROM otherthing.dbo.TBL_EVENT eve)

说必须在子查询的结果中找到com.COM_ID。但

INNER JOIN otherthing.dbo.TBL_EVENT eve
   ON com.COM_ID = eve.COM_ID 

表示要加入eve.COM_ID与com.COM_ID相同的所有帖子。

如果您在eve.COM_ID中有多个具有相同COM_ID的帖子,您的结果中会有多个帖子。

答案 1 :(得分:0)

这里没有什么是奇怪的,当TBL_EVENT中有超过1行与VIEW_REPORT和TBL_COMMUNICATION的1行连接匹配时会发生这种情况。

您不能像第二个脚本那样优化以获得相同的结果

您可以像下面那样优化sql,而不是重用第一个,这样可以提高脚本的速度

SELECT  
cus.*
, com.COM_ID
, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
LEFT JOIN otherthing.dbo.TBL_COMMUNICATION com 
ON com.REC_ID = cus.REC_ID 
AND com.RUN_ID = cus.RUN_ID 
and com.COM_ID in (
    SELECT distinct eve.COM_ID 
    FROM otherthing.dbo.TBL_EVENT eve)
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
ON cha.CHA_ID = com.CHA_ID 
INNER JOIN otherthing.dbo.TBL_EVENT eve
ON com.COM_ID = eve.COM_ID 

SELECT  
cus.*
, com.COM_ID
, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
LEFT JOIN (SELECT * FROM otherthing.dbo.TBL_COMMUNICATION com WHERE com.COM_ID IN (SELECT distinct eve.COM_ID FROM otherthing.dbo.TBL_EVENT eve)) com 
ON com.REC_ID = cus.REC_ID 
AND com.RUN_ID = cus.RUN_ID 
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
ON cha.CHA_ID = com.CHA_ID 

答案 2 :(得分:0)

你杀了LEFT JOIN otherthing.dbo.TBL_COMMUNICATION com与where,所以这会给你另一个答案。如果您更喜欢第一个答案,请将其更改为常规联接。

SELECT cus.*, com.COM_ID, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
LEFT JOIN otherthing.dbo.TBL_COMMUNICATION com 
       ON com.REC_ID = cus.REC_ID 
      AND com.RUN_ID = cus.RUN_ID 
      AND exists ( SELECT 1 
                   FROM otherthing.dbo.TBL_EVENT eve 
                   where eve.COM_ID = com.COM_ID )
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
       ON cha.CHA_ID = com.CHA_ID 

但是这个问题对我来说没有意义 为什么要限制左连接的右侧?
很确定你的意思是内部联接。

SELECT cus.*, com.COM_ID, cha.CHA_NAME
FROM thing.dbo.VIEW_REPORT cus --View
JOIN otherthing.dbo.TBL_COMMUNICATION com 
       ON com.REC_ID = cus.REC_ID 
      AND com.RUN_ID = cus.RUN_ID 
      AND exists ( SELECT 1 
                   FROM otherthing.dbo.TBL_EVENT eve 
                   where eve.COM_ID = com.COM_ID )
LEFT JOIN otherthing.dbo.TBL_CHANNEL cha
       ON cha.CHA_ID = com.CHA_ID 

发布查询计划