如何连接两个表并仅返回不匹配的行?

33

我有两个表,看起来像这样:

T1:  ID  |  Date  |  Hour  | Interval
T2:  ID  |  Date  |  Hour

我需要在它们的ID、日期和小时匹配时,将这些表连接起来。然而,我只想返回表1中那些与表2不匹配的结果。

我知道这看起来很简单,但我的问题是这样一个事实:表1中有多行与表2匹配(任何给定小时都有多个时间段)。只要它们不在表2的同一小时周期内,我就需要返回所有这些时间段。

示例数据:

T1:  1  |  1/1/2011  |  1  |  1
     1  |  1/1/2011  |  1  |  2
     1  |  1/1/2011  |  2  |  1
     1  |  1/1/2011  |  2  |  2

T2:  1  |  1/1/2011  |  1

我预期的结果集应该是来自T1的最后两行。有人可以指点我正确的方向吗?

2个回答

67
SELECT T1.*
    FROM T1
    WHERE NOT EXISTS(SELECT NULL
                         FROM T2
                         WHERE T1.ID = T2.ID 
                             AND T1.Date = T2.Date
                             AND T1.Hour = T2.Hour)

也可以使用 LEFT JOIN 来实现:

SELECT T1.*
    FROM T1
        LEFT JOIN T2
            ON T1.ID = T2.ID
                AND T1.Date = T2.Date
                AND T1.Hour = T2.Hour
    WHERE T2.ID IS NULL

谢谢您的回复,这两个查询在MS Access中都可以正常工作。说实话,我从来不知道你可以像那样组合SELECT语句,加一分。 - Breakthrough
实际上,还有一个回复 - 我选择了第一种选项,即WHERE NOT EXISTS子句。聪明极了,我从来不知道你可以这样做,它运行得非常好。 - Breakthrough
7
请记住,Jet/ACE查询处理器对NOT EXISTS的优化不太好,并且不会始终在比较的两侧使用索引(对于NOT IN来说,情况要严重得多)。因此,随着数据集的增长,使用NOT EXISTS可能会导致显著的性能下降。JOIN版本将始终利用所有可用的索引。 - David-W-Fenton

26

使用 LEFT JOIN 并过滤掉具有非NULL T2列的行:

SELECT T1.* FROM T1 LEFT JOIN T2 ON T1.ID = T2.ID
    AND T1.Date = T2.Date AND T1.Hour = T2.Hour
    WHERE T2.ID IS NULL

+1并感谢您的回答,但我不得不选择Joe的(他比您更早几分钟回答了)。 - Breakthrough

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接