如何在不使用“ EXCEPT”的情况下从重复表中查找丢失的数据

时间:2019-01-31 11:50:11

标签: sql sql-server

我曾经使用'EXCEPT'从应该具有相同数据但被告知不再使用它的2个表中查找丢失的数据。我找到了一个解决方案,但是我不完全确定它是如何工作的。有人可以给我解释一下还是帮我解决另一个问题?

这是我查询的基本示例:

SELECT MIN(C.TABLE_NAME) as TABLE_NAME,columnid,column
FROM
(
SELECT DISTINCT 'Source' as TABLE_NAME,columnid,column
FROM table1
UNION ALL
SELECT DISTINCT 'Output' as TABLE_NAME,columnid,column
FROM table2
) AS C
GROUP BY columnid,column
HAVING COUNT(*) = 1;

如果数据匹配,则输出结果不应显示任何行。上面的代码按预期在我在一个表上进行了测试,在该表上我知道数据是匹配的而不匹配的。我只是不确定它是如何工作的。很抱歉这个简单的问题。我是新来的。

编辑: 如果有帮助,我迅速制作了一些示例数据。

WITH salesman AS
(
SELECT 5005 AS id, 'Pit Alex' AS [name]
UNION ALL
SELECT 5006 AS id, 'Mc Lyon' AS [name]
UNION ALL
SELECT 5011 AS id, 'Lauson Hen' AS [name]
UNION ALL
SELECT 5007 AS id, 'Paul Adam' AS [name]
) ,
salesmancopy AS
(
SELECT 5005 AS id, 'Pit Alex' AS [name]
UNION ALL
SELECT 5006 AS id, 'Mc Lyon' AS [name]
UNION ALL
SELECT 5010 AS id, 'Lauson Hen' AS [name]
)

SELECT MIN(C.TABLE_NAME) as TABLE_NAME,id,[name]
FROM
(
 SELECT DISTINCT 'original' as TABLE_NAME,id,[name]
 FROM salesman
UNION ALL
 SELECT DISTINCT 'copy' as TABLE_NAME,id,[name]
 FROM salesmancopy
) AS C
GROUP BY id,[name]
HAVING COUNT(*) = 1;

3 个答案:

答案 0 :(得分:1)

如果您希望table1中的行不在table2中,那么仅当table2不包含某些唯一行时,您的解决方案才有效。换句话说,table2中的行必须存在于table1中。另一种解决方案是使用NOT EXISTS

select *
from table1 t1
where not exists (
   select 1
   from table2 t2
   where t1.columnid = t2.columnid and 
         t1.column = t2.column
)

Here,您可以看到针对此问题的不同方法的比较,其中NOT EXISTS解决方案优于LEFT JOIN + IS NULL解决方案。

答案 1 :(得分:1)

除了是确定一侧是否存在的最快方法。

但是,如果您想一次检查两个表,则可以使用FULL OUTER JOIN

IF OBJECT_ID('tempdb..#t1') IS NOT NULL
    DROP TABLE #t1;

IF OBJECT_ID('tempdb..#t2') IS NOT NULL
    DROP TABLE #t2;

SELECT *
  INTO #t1
  FROM (SELECT 1 AS num UNION SELECT 2 AS num UNION SELECT 3 AS num) d;

SELECT *
  INTO #t2
  FROM (SELECT 1 AS num UNION SELECT 2 AS num UNION SELECT 5 AS num) d;

SELECT            *
  FROM            #t1
  FULL OUTER JOIN #t2
    ON #t2.num = #t1.num
 WHERE            #t1.num IS NULL
    OR            #t2.num IS NULL;

输出:

enter image description here

答案 2 :(得分:-1)

要解决RadimBača提到的问题,即,如果您需要弄清两个表之间的差异,则当table2中不存在行但table1中存在行时,可以选择以下选项。

1.Create two column to indicate if the record is from original or copy
2.group by the columns you wish to compare.
3.use the clause having count(orig)<> count(copy)

使用与以前相同的查询,但进行小的更改,

WITH salesman AS
(
SELECT 5005 AS id, 'Pit Alex' AS [name]
UNION ALL
SELECT 5006 AS id, 'Mc Lyon' AS [name]
UNION ALL
SELECT 5011 AS id, 'Lauson Hen' AS [name]
UNION ALL
SELECT 5007 AS id, 'Paul Adam' AS [name]
) ,
salesmancopy AS
(
SELECT 5005 AS id, 'Pit Alex' AS [name]
UNION ALL
SELECT 5006 AS id, 'Mc Lyon' AS [name]
UNION ALL
SELECT 5010 AS id, 'Lauson Hen' AS [name]
)
SELECT c.id
       ,c.name
       ,count(orig) as present_in_orig
       ,count(copy) as present_in_copy
FROM
(
 SELECT 'original' as orig
        ,null      as copy
        ,id
        ,[name]
   FROM salesman
  UNION ALL
 SELECT null as orig
        ,'copy'    as copy
        ,id
        ,[name]
   FROM salesmancopy
) AS C
GROUP BY id
        ,[name]
HAVING COUNT(copy)<> count(orig)
order by 1,2

请参见Stew的以下链接,该链接非常详细地介绍了此方法。

https://stewashton.wordpress.com/2014/02/04/compare-and-sync-tables-tom-kyte-and-group-by/