微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql-server – 轻松显示两个表或查询之间不同的行

想象一下,您有两个不同的表/查询应该具有/返回相同的数据.你想验证这一点.如下例所示,比较每一列,从每个表中显示任何不匹配行的简单方法是什么?假设表中有30列,其中许多是NULLable.

当没有PK或每个PK可能存在重复时,仅加入PK列是不够的,如果必须使用正确处理NULL的30个连接条件进行全连接,加上令人讨厌的WHERE条件将是一场灾难.排除匹配的行.

通常情况下,当我正在编写一个新的查询时,针对未刷新或未完全理解的数据,问题最严重,并且PK在逻辑上可用的可能性非常低.我做了两种不同的方法解决问题,然后比较他们的结果,差异突出显示我不知道的数据中的特殊情况.

结果需要如下所示:

Which   Col1   Col2   Col3   ... Col30
------  ------ ------ ------     ------
TableA  Cat    27     86               -- mismatch
TableB  Cat    27     105              -- mismatch
TableB  Cat    27     87               -- mismatch 2
TableA  Cat    128    92               -- no corresponding row
TableB  Lizard 83     NULL             -- no corresponding row

如果[Col1,Col2]碰巧是一个复合键,我们在最终结果中按顺序排序,那么我们可以很容易地看到A和B有一行不同,应该是相同的,每一行都有一行不是在另一个.

在上面的例子中,不希望看到第一行两次.

这是用于设置样本表和数据的DDL和DML:

CREATE TABLE dbo.TableA (
   Col1 varchar(10),Col2 int,Col3 int,Col4 varchar(10),Col5 varchar(10),Col6 varchar(10),Col7 varchar(10),Col8 varchar(10),Col9 varchar(10),Col10 varchar(10),Col11 varchar(10),Col12 varchar(10),Col13 varchar(10),Col14 varchar(10),Col15 varchar(10),Col16 varchar(10),Col17 varchar(10),Col18 varchar(10),Col19 varchar(10),Col20 varchar(10),Col21 varchar(10),Col22 varchar(10),Col23 varchar(10),Col24 varchar(10),Col25 varchar(10),Col26 varchar(10),Col27 varchar(10),Col28 varchar(10),Col29 varchar(10),Col30 varchar(10)
);

CREATE TABLE dbo.TableB (
   Col1 varchar(10),Col30 varchar(10)
);

INSERT dbo.TableA (Col1,Col2,Col3,Col4,Col5,Col6,Col7,Col8,Col9,Col10,Col11,Col12,Col13,Col14,Col15,Col16,Col17,Col18,Col19,Col20,Col21,Col22,Col23,Col24,Col25,Col26,Col27,Col28,Col29,Col30)
VALUES
   ('Cat',27,86,'a','b','c','d','e','f','g',' h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0'),('Cat',128,92,('Porcupine',NULL,42,('Tapir','0')
;

INSERT dbo.TableB (Col1,105,87,('Lizard',83,'0');

解决方法

这里的FULL OUTER JOIN不需要30个连接条件.

您可以在PK上进行全外连接,保留与WHERE EXISTS(SELECT A. * EXCEPT SELECT B. *)至少有一个区别的行,并使用CROSS APPLY(SELECT A. * UNION ALL SELECT B. *)来取消JOINed行的两侧分成各行.

WITH TableA(Col1,Col3) 
     AS (SELECT 'Dog',1,1     UNION ALL 
         SELECT 'Cat',86   UNION ALL 
         SELECT 'Cat',92),TableB(Col1,105  UNION ALL 
         SELECT 'Lizard',NULL) 
SELECT CA.*
FROM   TableA A 
       FULL OUTER JOIN TableB B 
         ON A.Col1 = B.Col1 
            AND A.Col2 = B.Col2 
/*Unpivot the joined rows*/
CROSS APPLY (SELECT 'TableA' AS what,A.* UNION ALL
             SELECT 'TableB' AS what,B.*) AS CA     
/*Exclude identical rows*/
WHERE  EXISTS (SELECT A.* 
               EXCEPT 
               SELECT B.*) 
/*discard NULL extended row*/
AND CA.Col1 IS NOT NULL      
ORDER BY CA.Col1,CA.Col2

what   Col1   Col2        Col3
------ ------ ----------- -----------
TableA Cat    27          86
TableB Cat    27          105
TableA Cat    128         92
TableB Lizard 83          NULL

或者是处理移动的球门柱的版本.

SELECT disTINCT CA.*
FROM   TableA A 
       FULL OUTER JOIN TableB B 
         ON EXISTS (SELECT A.*  INTERSECT  SELECT B.*) 
CROSS APPLY (SELECT 'TableA' AS what,B.*) AS CA     
WHERE NOT EXISTS (SELECT A.*  INTERSECT  SELECT B.*) 
AND CA.Col1 IS NOT NULL
ORDER BY CA.Col1,CA.Col2

原文地址:https://www.jb51.cc/mssql/80688.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐