【问题标题】:T-SQL: Comparing Two Tables - Records that don't exist in second tableT-SQL:比较两个表 - 第二个表中不存在的记录
【发布时间】:2008-12-16 18:00:29
【问题描述】:

如果UNION ALL 是T-SQL 中的添加。减法的等价物是什么?

例如,如果我有一个表 PEOPLE 和一个表 EMPLOYEES。而且我知道如果我从PEOPLE 中删除EMPLOYEES 记录,我将留在我的公司CONTRACTORS

有没有类似于UNION ALL 的方法?一个我不必指定任何字段名称的地方?我问的原因是这只是一个假设的例子。我需要对许多不同的表多次执行此操作。假设EMPLOYEESPEOPLE的schema是一样的。

【问题讨论】:

    标签: sql sql-server-2005 tsql


    【解决方案1】:

    您可以使用EXCEPT operator 从另一组中减去一组。这是使用 EMPLOYEES 和 PEOPLE 临时表的代码示例。据我所知,您需要将字段名称与 EXCEPT 运算符一起使用。

    CREATE TABLE #PEOPLE
    (ID INTEGER,
     Name NVARCHAR(50))
    
    CREATE TABLE #EMPLOYEE
    (ID INTEGER,
     Name NVARCHAR(50))
    GO
    
    INSERT #PEOPLE VALUES (1, 'Bob')
    INSERT #PEOPLE VALUES (2, 'Steve')
    INSERT #PEOPLE VALUES (3, 'Jim')
    INSERT #EMPLOYEE VALUES (1, 'Bob')
    GO
    
    SELECT ID, Name
    FROM #PEOPLE
    EXCEPT 
    SELECT ID, Name
    FROM #EMPLOYEE
    GO
    

    最终查询将返回 PEOPLE 表中不存在于 EMPLOYEE 表中的两行。

    【讨论】:

    • 请记住,EXCEPT 只会为您提供 DISTINCT 值。在您的情况下,如果您添加另一个 id =2 的史蒂夫,那么无论如何您只会得到其中一个。当然,ID 可能是主键。
    【解决方案2】:

    不要使用 UNION,而是使用 EXCEPT,(或 INTERSECT 只获取两者中的记录) 如

    中所述

    msdn EXCEPT Link for Sql2k8

    msdn EXCEPT Link for Sql2k5

    【讨论】:

      【解决方案3】:
      SELECT
           P.*
      FROM
           People P
      LEFT OUTER JOIN Employees E ON
           E.ID = P.ID     -- Or whatever your PK-FK relationship is
      WHERE
           E.ID IS NULL
      

      对于 SQL Server,这可能是您能做到的最高效的方式。

      【讨论】:

      • 两个人认为返回正确答案的解决方案值得否决,而无需解释原因。他们何时会实施该功能以要求对否决发表评论? :)
      • 左外连接返回左表中的所有记录,无论是否在第二个表中找到匹配项。当您只想从第一个表中获取第二个表中不存在的那些记录时,不能使用它。 :)
      • 这就是 WHERE 子句包含“E.ID IS NULL”的原因。在宣布有问题之前,您可能应该了解它并进行理想的测试。
      • 我同意你的观点,你的解决方案在 SQL Server 中更快。请阅读这篇文章sqlservercentral.com/Forums/Topic541726-338-1.aspx
      • 这是一个很好的解决方案,但是,在最近做一些性能分析时,我遇到了这样的情况,这样做不一定是最好的选择。据我所知,原因是如果连接会导致大量连接记录,SQL 必须执行连接才能执行 IS NULL 测试。在这些情况下,在 where 子句中使用子查询会快得多,例如 WHERE NOT EXISTS(Select 1 from Employees e where e.id = p.id)。这很大程度上取决于两个表的相对大小。
      【解决方案4】:
      SELECT * FROM Table1
      WHERE Table1.Key NOT IN (SELECT Table2.Key FROM Table2 WHERE Table2.Key IS NOT NULL)
      

      添加了 IS NOT NULL 以使人们开心。

      我同意汤姆的观点。他的版本很可能更有效。使用我的唯一可能的原因可能是它更漂亮。

      【讨论】:

      • “Table2.Key”中的空值失败。
      • 添加 IS NOT NULL 然后,如果您期望 NULL,但我假设 Table2.Key 是 PK 并且没有 NULL
      【解决方案5】:

      很遗憾,您的设计存在问题。 而不是有两个表 PEOPLE 和 CONTRACTOR。 您应该有一个表 PEOPLE 和另一个表 TYPE(如果某些人可以担任多个角色,则可能需要另一个表)。 在您的 PEOPLE 表中,您可以参考 TYPE 表。

      那么你的要求就变成了

      SELECT * from PEOPLE, TYPE
      WHERE PEOPLE.type_id = TYPE.id 
      AND TYPE.name = 'CONTRACTOR'
      
      SELECT * from PEOPLE, TYPE
      WHERE PEOPLE.type_id = TYPE.id 
      AND TYPE.name = 'EMPLOYEE'
      

      (未经测试)

      【讨论】:

      • 这只是一个例子。同意这个设计很糟糕。
      【解决方案6】:

      当我比较表以查找不在另一个中的数据时,我通常使用 SQL 分区。

      select *(or selected matching field) 
      from tableA as A
      where not exist
      (select *(or selected matching field) 
      from tableB as B 
      where A.key = B.key)
      

      此查询将返回tableA中没有经过除法处理的结果。

      select *(or selected matching field) 
      from tableA as A
      where exist
      (select *(or selected matching field) 
      from tableB as B 
      where A.key = B.key)
      

      此查询将返回两个表中匹配的所有数据行,因此如果 tableA 中的行数据不在 tableB 中,则不会检索该行数据。

      【讨论】:

        【解决方案7】:

        我发现使用 SQLMerger 之类的工具为您执行此操作要容易得多。结果以更好的方式显示,之后您可以轻松地继续处理您需要对数据执行的任何操作。

        www.auisoft.com/SQLMerger

        比较两个表的示例:http://auisoft.com/SQLMerger/How-to/visualize-differences-in-2-databases/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-05
          • 2018-02-25
          • 1970-01-01
          • 2019-09-12
          相关资源
          最近更新 更多