在哪里+不存在+ 2列

时间:2013-10-10 08:15:18

标签: sql sql-server

我有一个查询,它应该返回T1中没有链接到T2中记录的所有记录:

SELECT DISTINCT fldID, fldValue FROM T1 
 WHERE NOT EXISTS
 (
  SELECT  T1.fldID, T1.fldValue
    FROM T2
    JOIN T1  ON T2.fldID = T1.fldPtr
 )      

但是它返回空集 - 应该是一个记录。

如果我使用这样的查询(一个字段的子句):

SELECT DISTINCT fldID FROM T1 
 WHERE fldID NOT IN
 (
  SELECT  T1.fldID
    FROM T2
   JOIN T1  ON T2.fldID = T1.fldPtr
 )      

返回正确的结果。

但SQL Server不支持语法

WHERE ( fldID, flrValue ) NOT IN .... 

请帮助我弄清楚如何编写将检查多个列的查询?

谢谢!

9 个答案:

答案 0 :(得分:5)

您也可以使用EXCEPT

SELECT DISTINCT fldID, fldValue FROM T1 

EXCEPT

SELECT  T1.fldID, T1.fldValue
FROM T2
    JOIN T1  ON T2.fldID = T1.fldPtr

答案 1 :(得分:2)

适用于每个数据库的更高效,更优雅的查询是:

SELECT T1.*
FROM T1
LEFT JOIN T2
    ON T2.fldID = T1.fldPtr
    AND T2.flrValue = T1.flrValue
WHERE T2.fldID IS NULL

LEFT JOIN尝试使用两个条件匹配,然后WHERE子句过滤联接,只有非联接具有LEFT JOINed表的NULL值。

这种方法是恕我直言,几乎是寻找不匹配的行业标准。它通常比NOT EXIstS()更有效,尽管有几个数据库无论如何都优化了NOT EXISTS()。

答案 2 :(得分:1)

如果子查询加入,请使用这两列:

SELECT DISTINCT fldID, fldValue FROM T1 
WHERE NOT EXISTS
(
    SELECT * 
    FROM T2
    JOIN T1 ON T2.fldID = T1.fldPtr
           AND T1.fldValue = T2.flrValue 
)   

答案 3 :(得分:0)

类似的东西(我想,因为我不确定我100%理解你的问题):

SELECT DISTINCT fldID FROM T1 
 WHERE fldID NOT IN
 (
  SELECT  T1.fldID
    FROM T2
   JOIN T1  ON T2.fldID = T1.fldPtr
  WHERE T2.flrValue = T1.flrValue
 )  

答案 4 :(得分:0)

如果两个表中的结构相同,则可以使用EXCEPT运算符http://technet.microsoft.com/en-us/library/ms188055.aspx

在更一般的情况下,您必须使用左连接并在第二个表中查找空元素。

答案 5 :(得分:0)

尝试以下查询。

select DISTINCT fldID
from Table1
WHERE cast(fldID as varchar(100))+'~'+cast(flrValue as varchar) 
NOT IN (select cast(fldID as varchar(100))+'~'+cast(flrValue as varchar) from table2)

答案 6 :(得分:0)

这是更容易查询。它返回所有未链接到T2

中记录的T1.fldID
SELECT DISTINCT T1.fldID
FROM T1
LEFT JOIN T2 ON T2.fldID = T1.fldPtr
WHERE T2.fldID IS NULL

答案 7 :(得分:0)

使用IN排除大量值对于性能而言非常糟糕。请尝试以下方法:

SELECT T1.*
FROM T1
    LEFT JOIN T2 ON T2.fldID = T1.fldPtr AND T1.fldValue = T2.fldvalue
WHERE T2.fldID IS NULL

答案 8 :(得分:0)

(从我的评论:)您不必在子查询中再次引用t1。这样做会导致select all the records from t1 that don't exist in t1 ...形式的逻辑,它始终为空,就像select all blue balls that are not blueselect all odd numbers that are even一样...... 第一个查询应该是:

SELECT DISTINCT fldID, fldValue
FROM T1 
WHERE NOT EXISTS (
  SELECT * FROM T2
   WHERE T2.fldID = T1.fldPtr
 );

并且:在原始查询中,子查询不相关:子查询中的t1 阴影主查询中的t1,使子查询不引用主查询中的任何表或别名:它返回True(某些行存在)或False,结果与主查询中的行完全不相关。 (使用别名而不是查询中的真实表名称的另一个好理由)