sql查询返回两个表之间的差异

Cas*_*sey 183 sql sql-server sql-server-2005 sql-server-2008

我试图比较两个表,SQL Server,以验证一些数据.我想从两个表中返回所有行,其中数据在一个或另一个中.从本质上讲,我想表明所有的差异.我需要检查三个数据,FirstName,LastName和Product.

我对SQL很新,似乎很多我发现的解决方案都让事情变得复杂.我不必担心NULL.

我开始尝试这样的事情:

SELECT DISTINCT [First Name], [Last Name], [Product Name] FROM [Temp Test Data]
WHERE ([First Name] NOT IN (SELECT [First Name] 
FROM [Real Data]))
Run Code Online (Sandbox Code Playgroud)

我在进一步考虑这个问题时遇到了麻烦.

谢谢!

编辑:

根据@treaschf的回答,我一直在尝试使用以下查询的变体:

SELECT td.[First Name], td.[Last Name], td.[Product Name]
FROM [Temp Test Data] td FULL OUTER JOIN [Data] AS d 
ON td.[First Name] = d.[First Name] AND td.[Last Name] = d.[Last Name] 
WHERE (d.[First Name] = NULL) AND (d.[Last Name] = NULL)
Run Code Online (Sandbox Code Playgroud)

但是当我知道td中至少有一行不在d中时,我一直得到0结果.

编辑:

好吧,我想我弄明白了.至少在我测试的几分钟内它似乎工作得很好.

SELECT [First Name], [Last Name]
FROM [Temp Test Data] AS td
WHERE (NOT EXISTS
        (SELECT [First Name], [Last Name]
         FROM [Data] AS d
         WHERE ([First Name] = td.[First Name]) OR ([Last Name] = td.[Last Name])))
Run Code Online (Sandbox Code Playgroud)

这基本上会告诉我我的测试数据中有哪些不在我的真实数据中.这对我需要做的事情来说完全没问题.

eri*_*len 234

(   SELECT * FROM table1
    EXCEPT
    SELECT * FROM table2)  
UNION ALL
(   SELECT * FROM table2
    EXCEPT
    SELECT * FROM table1) 
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.有没有办法可以添加一个字段,告诉我返回的记录来自哪两个表? (4认同)
  • 在 Big Query 中不起作用:`消息:EXCEPT 后面必须跟有 ALL、DISTINCT 或“(”` (4认同)
  • 如果您收到错误,则需要确保以相同的顺序选择相同的字段(相同类型).`SELECT*`适用于所有列的情况; 如果没有,只需选择一些子集. (3认同)
  • 请小心,因为此解决方案会丢弃重复项。 (3认同)
  • @motobói 使用 BigQuery 我面临着同样的问题。我发现 BigQuery 仅支持“EXCEPT DISTINCT”。不幸的是,BigQuery 不支持“EXCEPT ALL”。 (3认同)
  • 我也收到错误消息 205,级别 16,状态 1,第 5 行 使用 UNION、INTERSECT 或 EXCEPT 运算符组合的所有查询在其目标列表中必须具有相同数量的表达式。 (2认同)
  • 我改为使用INTERSECT,但感谢您的提示。 (2认同)

tre*_*chf 196

如果你有表格,A并且B都有colum C,这里是记录,这些记录存在于表中A但不在B:

SELECT A.*
FROM A
    LEFT JOIN B ON (A.C = B.C)
WHERE B.C IS NULL
Run Code Online (Sandbox Code Playgroud)

要通过单个查询获得所有差异,必须使用完整连接,如下所示:

SELECT A.*, B.*
FROM A
    FULL JOIN B ON (A.C = B.C)
WHERE A.C IS NULL OR B.C IS NULL
Run Code Online (Sandbox Code Playgroud)

在这种情况下你需要知道的是,当一个记录可以找到A而不是B来自那些来自的列时B将是NULL,并且类似于那些存在于B和不存在A的列中的列A将来自是空的.

  • `FROM 子句中的对象“a.dbo.student”和“b.dbo.student”具有相同的公开名称。使用相关名称来区分它们。如果表名称相同并且您从两个不同的数据库中提取它们,我会收到错误。 (2认同)

小智 37

我知道这可能不是一个流行的答案,但我同意@Randy Minder在需要进行更复杂的比较时使用第三方工具.

这里的具体情况很简单,对于这种情况,不需要这样的工具,但如果在两台服务器上引入更多列,数据库,更复杂的比较标准等,这可能会变得很复杂.

有很多这样的工具,如ApexSQL Data DiffQuest Toad,你总是可以在试用模式下使用它们来完成工作.


bil*_*tch 14

要获得两个表之间的所有差异,您可以像我一样使用此SQL请求:

SELECT 'TABLE1-ONLY' AS SRC, T1.*
FROM (
      SELECT * FROM Table1
      EXCEPT
      SELECT * FROM Table2
      ) AS T1
UNION ALL
SELECT 'TABLE2-ONLY' AS SRC, T2.*
FROM (
      SELECT * FROM Table2
      EXCEPT
      SELECT * FROM Table1
      ) AS T2
;
Run Code Online (Sandbox Code Playgroud)


Rom*_*kar 6

如果要获取哪些列值不同,则可以使用Entity-Attribute-Value模型:

declare @Data1 xml, @Data2 xml

select @Data1 = 
(
    select * 
    from (select * from Test1 except select * from Test2) as a
    for xml raw('Data')
)

select @Data2 = 
(
    select * 
    from (select * from Test2 except select * from Test1) as a
    for xml raw('Data')
)

;with CTE1 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data1.nodes('Data/@*') as T(C)    
), CTE2 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data2.nodes('Data/@*') as T(C)     
)
select
    isnull(C1.ID, C2.ID) as ID, isnull(C1.Name, C2.Name) as Name, C1.Value as Value1, C2.Value as Value2
from CTE1 as C1
    full outer join CTE2 as C2 on C2.ID = C1.ID and C2.Name = C1.Name
where
not
(
    C1.Value is null and C2.Value is null or
    C1.Value is not null and C2.Value is not null and C1.Value = C2.Value
)
Run Code Online (Sandbox Code Playgroud)

SQL范例


stu*_*eek 5

@erikkallen答案的简单变化,显示该行存在于哪个表中:

(   SELECT 'table1' as source, * FROM table1
    EXCEPT
    SELECT * FROM table2)  
UNION ALL
(   SELECT 'table2' as source, * FROM table2
    EXCEPT
    SELECT * FROM table1) 
Run Code Online (Sandbox Code Playgroud)

如果遇到错误

使用UNION,INTERSECT或EXCEPT运算符组合的所有查询的目标列表中必须具有相等数量的表达式。

那么可能有助于添加

(   SELECT 'table1' as source, * FROM table1
    EXCEPT
    SELECT 'table1' as source, * FROM table2)  
UNION ALL
(   SELECT 'table2' as source, * FROM table2
    EXCEPT
    SELECT 'table2' as source, * FROM table1) 
Run Code Online (Sandbox Code Playgroud)

  • 我收到错误消息`使用 UNION、INTERSECT 或 EXCEPT 运算符组合的所有查询在其目标列表中必须具有相同数量的表达式。` 使用此选择。我必须将 `'table1' 作为源添加,` 部分也添加到例外部分。- 我为此编辑了答案。 (2认同)