使用EXCEPT与INTERSECT进行Transact SQL

时间:2015-03-23 18:36:00

标签: sql sql-server-2008 tsql

我有两个SQL表,其密钥基于First_Name,Last_Name&出生日期。 我正在尝试编写一个简单的transact sql来查找Table2中找不到Table1 Patient_Key的异常

表1包含152758条记录,并且每月都是一个新数据集  表2包含8388条记录并将继续增长

所以我现在的查询需要花费半小时才能返回零结果(我知道由于为不同的Patient_Keys分别手动查询每个表,因此没有结果 以下是查询:

 SELECT T1.*
 FROM TABLE1 T1
 WHERE  upper(T1.FIRST_NAME)  + UPPER(t1.LAST_NAME) + 
 REPLACE(CONVERT(VARCHAR (10), T1.DATE_OF_BIRTH, 120), '-','') NOT IN 
 (SELECT DISTINCT upper(T2.FIRST_NAME)  + UPPER(T2.LAST_NAME) +
 REPLACE(CONVERT(VARCHAR (10), T2.DATE_OF_BIRTH, 120), '-','')
 FROM TABLE2 T2)

是否有更高效的SQL成本节省方法?

3 个答案:

答案 0 :(得分:4)

我建议left join

 SELECT T1.*
 FROM TABLE1 T1 LEFT JOIN
      TABLE2 T2
      ON t1.first_name = t2.first_name AND
         t1.last_name = t2.last_name AND
         t1.date_of_birth = t2.date_of_birth
 WHERE t2.first_name IS NULL;

查询的问题是连接。如果您所处的环境具有区分大小写的排序规则,则应在两个表中添加单个大小写的计算列。

对于此查询,请在table2(first_name, last_name, date_of_birth)上创建索引。这应该可以为您提供所需的性能。

答案 1 :(得分:2)

检查多个键之间存在的行与WHERE NOT EXISTS相关子查询相比效果更好:

SELECT *
FROM Table1 T1
WHERE NOT EXISTS (
        SELECT 1 
        FROM Table2 T2
        WHERE T2.FIRST_NAME = T1.FIRST_NAME
            AND T2.LAST_NAME = T1.LAST_NAME
            AND T2.DATE_OF_BIRTH = T1.DATE_OF_BIRTH
    )

如果您的数据库实际配置为使用区分大小写的排序规则,则应使用COLLATE选项强制执行不区分大小写的比较。效率明显提高。无论您的配置如何,都应该有一个等效的不区分大小写的排序规则。

SELECT *
FROM Table1 T1
WHERE NOT EXISTS (
        SELECT 1 
        FROM Table2 T2
        WHERE T2.FIRST_NAME = T1.FIRST_NAME COLLATE SQL_Latin1_General_CP1_CI_AS
            AND T2.LAST_NAME = T1.LAST_NAME COLLATE SQL_Latin1_General_CP1_CI_AS
            AND T2.DATE_OF_BIRTH = T1.DATE_OF_BIRTH
    )

如果您在Table1 (FIRST_NAME, LAST_NAME, DATE_OF_BIRTH)Table2 (FIRST_NAME, LAST_NAME, DATE_OF_BIRTH)上有索引,那么您的表现应该会更好。

答案 2 :(得分:0)

避免转换和连接

;WITH NotInT2 AS (
    SELECT first_name, last_name, date_of_birth
    FROM   t1
    EXCEPT
    SELECT first_name, last_name, date_of_birth
    FROM   t2
)
SELECT *
FROM   t1
JOIN   NotInT2
    ON NotInT2.first_name = t1.first_name
   AND NotInT2.last_name = t1.last_name
   AND NotInT2.date_of_birth = t1.date_of_birth

此外,如果有必要,只使用UPPER()功能