将两个表与特定结果进行比较

时间:2018-03-21 18:57:32

标签: sql sql-server tsql

我想比较两张桌子。我们的程序的工作方式是,如果一个人被更改,它会更新记录并将原始数据抛出到新表中。

我能够创建一个有效的查询。但是,它只返回已更改的行。不知何故,我需要它来返回旧的和新的,并指出改变了什么。有没有办法做到这一点?

所以在这个例子中,在那里抛出另一个东西(对不起)Jon Doe不应该出现,因为没有真正改变。他的一个电话号码从一个电话领域转移到另一个电话领域。有这么多像这样,我的新版本仍然没有正确处理它们。

Jane应该出现,因为她的电子邮件发生了变化。然而,它只是返回该记录。我看不出改变了什么,或原始价值是什么。

无论哪种方式都必须说出类似的话。 (我会跳过细节)但是以某种格式让他们可以看到改变了什么。

Creating 4
Creating 3
Creating 2
Creating 1
Creating 0

康拉德的ETA变更(谢谢)

BEFORE                    AFTER             CHANGED
Name: Jane Smith          Jane Smith
Address: 111 East Grove   111 East Grove
Etc.
Email:  janeR@gmail.com   janes@gmail.com    Yes

2 个答案:

答案 0 :(得分:0)

您的问题与How can I write a query to extract individual changes from snapshots of data?之间的主要区别在于您只有两条记录可以竞争而不是N条记录。此外,您似乎想要所有值,但想知道它们是否已更改。

;with data as (
SELECT *
FROM [#Source] [S]
    INNER JOIN [#Target] [T]
    ON [S].[ID] = [T].[pov_Prospect]

)

, fieldsToRows 
     AS (SELECT 
            id,
            field,
            Value

         FROM   data p UNPIVOT (value FOR field IN (nameFull, pov_nameFull, 
                                                salutation, pov_salutation, 
                                                nameFirst, pov_nameFirst, 
                                                nameLast, pov_nameLast, 
                                                addressLine1, pov_addressLine1, 
                                                addressLine2, pov_addressLine2, 
                                                addressCity, pov_addressCity, 
                                                addressState, pov_addressState, 
                                                addressZip, pov_addressZip, 
                                                phone1full, pov_phone1full, 
                                                phone2full, pov_phone2full, 
                                                phone3full, pov_phone3full, 
                                                phone4full, pov_phone4full, 
                                                phone5full, pov_phone5full, 
                                                email1, pov_email1    ) ) 
                AS unpvt
        ) 
SELECT 
        curr.id,
        curr.field,
        curr.value new_value,
        prev.value  old_value,
        CASE WHEN curr.value <> prev.value THEN 'Yes'  END Changed

FROM 
        fieldsToRows curr 
        INNER  JOIN  fieldsToRows prev
        ON curr.ID = prev.id
            AND 'pov_' + curr.field  =  prev.field

Demo

由于您的数据为空,因此您必须与Handle NULL value in UNPIVOT抗争

在我的演示中,我将ISNULL添加到每个字段中,但为了简洁起见,将其留在上面

如果您想要消除没有变化的行,您需要添加一系列OR条款,例如ISNULL( s.nameFull, '') <> ISNULL( t.pov_nameFull, '')

请参阅Demo

这并不涉及移动的字段。为此,您需要做一些事情OR (phone1 <> pov_phone1 and phone1 <> pov_phone2 AND... ) OR

我将如何处理不同的数据类型(你的所有varchar(50))留给你

答案 1 :(得分:0)

我是从Conrad Frix的回答开始的,但是我将源代码和目标分开了,所以我们也可以找到涉及空值的差异:

;with SourceFieldsToRows AS (
    SELECT id, field, Value
    FROM   #Source s UNPIVOT (Value FOR field IN (nameFull, salutation, nameFirst, nameLast, addressLine1, addressLine2, addressCity, addressState, addressZip, phone1full, phone2full, phone3full, phone4full, phone5full, email1)) u
), TargetFieldsToRows AS (
    SELECT u.pov_Prospect, field, Value
    FROM   #Target t UNPIVOT (Value FOR field IN (pov_nameFull, pov_salutation, pov_nameFirst, pov_nameLast, pov_addressLine1, pov_addressLine2, pov_addressCity, pov_addressState, pov_addressZip, pov_phone1full, pov_phone2full, pov_phone3full, pov_phone4full, pov_phone5full, pov_email1)) u
)
SELECT  ISNULL(curr.id,prev.pov_Prospect) AS id,
        ISNULL(curr.field,prev.field) AS field,
        curr.value AS new_value,
        prev.value AS old_value,
        CASE WHEN curr.value <> prev.value OR curr.value IS NULL AND prev.value IS NOT NULL OR curr.value IS NOT NULL AND prev.value IS NULL THEN 'Yes' END Changed
FROM SourceFieldsToRows curr 
FULL OUTER  JOIN  TargetFieldsToRows prev 
    ON curr.ID = prev.pov_Prospect AND 'pov_' + curr.field  =  prev.field