Sql 查找具有相同模式、在相同输出中具有更改和原始值的表之间的差异

Sql 查找具有相同模式、在相同输出中具有更改和原始值的表之间的差异,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有两个表,每个表都有相同的模式 第一个(或从此处开始的OldDataTable)如下所示: | PlantID | OutletId | BusinessTypeID | TradeChannelID| |---------|-----------|----------------|----------------| |I000 | 500113730 | 1 | 8| |I000 | 500113772 | 1 | 12| |1000 | 500113819 | 1 | 40| |I000

我有两个表,每个表都有相同的模式

第一个(或从此处开始的
OldDataTable
)如下所示:

| PlantID | OutletId | BusinessTypeID | TradeChannelID|
|---------|-----------|----------------|----------------|
|I000 | 500113730 | 1 | 8|
|I000 | 500113772 | 1 | 12|
|1000 | 500113819 | 1 | 40|
|I000 | 500113821 | 1 | 8|
|I000 | 500113848 | 1 | 7|
第二个(或从此处开始的
NewDataTable
)如下所示:

| PlantID | OutletId | BusinessTypeID | TradeChannelID|
|---------|-----------|----------------|----------------|
|I000 | 500113730 | 2 | 5|
|I000 | 500113772 | 1 | 12|
|1000 | 500113819 | 1 | 40|
|I000 | 500113821 | 1 | 8|
|I000 | 500113848 | 1 | 7|
你可以看到,有一些不同。对于给定的
OutletId
(500113730),
BusinessTypeID
TradeChannelID
NewDataTable
中更改,而不是在
OldDataTable
中更改

我想不出一个查询能完成我要找的。我需要一个查询,生成一个输出,显示更改的
OutletID
,然后显示更改的内容及其原始值。鉴于上述两个示例,结果应如下所示:

| PlantID | Change|u PlantID | OutletID | Change|u OutletID | BusinessTypeID | Change|u BusinessTypeID | TradeChannelID | Change|u TradeChannelID ||
|---------|----------------|-----------|-----------------|----------------|-----------------------|----------------|-----------------------|
|1000 | 500113730 | 1 | 2 | 8 | 5|
有几件事需要注意:


如果有任何更改,应用程序并不总是知道更改了什么。输出仅显示更改的
OutletId
s

使用检查任何不同内容的约束将两个表连接在一起应该很容易:

SELECT
    old.PlantID
    ,old.OutletID
    ,old.BusinessTypeID
    ,new.BusinessTypeID AS Change_BusinessTypeID
    ,old.TradeChannelID
    ,new.TradeChannelID AS Change_TradeChannelID
FROM
    OldDataTable old
FULL OUTER JOIN
    NewDataTable new
    ON
    old.PlantID = new.PlantID
    AND
    old.OutletID = new.OutletID
WHERE
    (
        old.BusinessTypeID <> new.BusinessTypeID
        OR
        old.TradeChannelID <> new.TradeChannelID
    )
选择
老花
,老外
,old.BusinessTypeID
,new.BusinessTypeID作为Change\u BusinessTypeID
,old.TradeChannelID
,new.TradeChannelID作为Change\u TradeChannelID
从…起
旧数据表旧
完全外接
新建数据表新建
在…上
old.PlantID=new.PlantID
及
old.OutletID=new.OutletID
哪里
(
old.BusinessTypeID new.BusinessTypeID
或
old.TradeChannelID new.TradeChannelID
)
这不会隐藏一列的旧/新对,而同一行中的另一列没有更改,但您可以在选择列表中轻松添加一些检查(例如,
选择CASE WHEN old.column new.column然后old.column END

更新-如果要处理结果中只包含每列更改的内容的情况,则语句可能是这样的:

SELECT
    old.PlantID
    ,old.OutletID
    ,(CASE WHEN old.BusinessTypeID <> new.BusinessTypeID THEN old.BusinessTypeID END) AS BusinessTypeID
    ,(CASE WHEN old.BusinessTypeID <> new.BusinessTypeID THEN new.BusinessTypeID END) AS Change_BusinessTypeID
    ,(CASE WHEN old.TradeChannelID <> new.TradeChannelID THEN old.TradeChannelID END) AS TradeChannelID
    ,(CASE WHEN old.TradeChannelID <> new.TradeChannelID THEN new.TradeChannelID END) AS Change_TradeChannelID
FROM
    OldDataTable old
FULL OUTER JOIN
    NewDataTable new
    ON
    old.PlantID = new.PlantID
    AND
    old.OutletID = new.OutletID
WHERE
    (
        old.BusinessTypeID <> new.BusinessTypeID
        OR
        old.TradeChannelID <> new.TradeChannelID
    )
选择
老花
,老外
,(当old.BusinessTypeID为new.BusinessTypeID时为大小写,然后old.BusinessTypeID为END)作为BusinessTypeID
,(当old.BusinessTypeID为new.BusinessTypeID时,则为new.BusinessTypeID结束)作为Change\u BusinessTypeID
,(当old.TradeChannelID为new.TradeChannelID时,则为old.TradeChannelID结束)作为TradeChannelID
,(当old.TradeChannelID为new.TradeChannelID时,则为new.TradeChannelID结束)作为Change\u TradeChannelID
从…起
旧数据表旧
完全外接
新建数据表新建
在…上
old.PlantID=new.PlantID
及
old.OutletID=new.OutletID
哪里
(
old.BusinessTypeID new.BusinessTypeID
或
old.TradeChannelID new.TradeChannelID
)

使用检查不同内容的约束将两个表连接在一起应该很容易:

SELECT
    old.PlantID
    ,old.OutletID
    ,old.BusinessTypeID
    ,new.BusinessTypeID AS Change_BusinessTypeID
    ,old.TradeChannelID
    ,new.TradeChannelID AS Change_TradeChannelID
FROM
    OldDataTable old
FULL OUTER JOIN
    NewDataTable new
    ON
    old.PlantID = new.PlantID
    AND
    old.OutletID = new.OutletID
WHERE
    (
        old.BusinessTypeID <> new.BusinessTypeID
        OR
        old.TradeChannelID <> new.TradeChannelID
    )
选择
老花
,老外
,old.BusinessTypeID
,new.BusinessTypeID作为Change\u BusinessTypeID
,old.TradeChannelID
,new.TradeChannelID作为Change\u TradeChannelID
从…起
旧数据表旧
完全外接
新建数据表新建
在…上
old.PlantID=new.PlantID
及
old.OutletID=new.OutletID
哪里
(
old.BusinessTypeID new.BusinessTypeID
或
old.TradeChannelID new.TradeChannelID
)
这不会隐藏一列的旧/新对,而同一行中的另一列没有更改,但您可以在选择列表中轻松添加一些检查(例如,
选择CASE WHEN old.column new.column然后old.column END

更新-如果要处理结果中只包含每列更改的内容的情况,则语句可能是这样的:

SELECT
    old.PlantID
    ,old.OutletID
    ,(CASE WHEN old.BusinessTypeID <> new.BusinessTypeID THEN old.BusinessTypeID END) AS BusinessTypeID
    ,(CASE WHEN old.BusinessTypeID <> new.BusinessTypeID THEN new.BusinessTypeID END) AS Change_BusinessTypeID
    ,(CASE WHEN old.TradeChannelID <> new.TradeChannelID THEN old.TradeChannelID END) AS TradeChannelID
    ,(CASE WHEN old.TradeChannelID <> new.TradeChannelID THEN new.TradeChannelID END) AS Change_TradeChannelID
FROM
    OldDataTable old
FULL OUTER JOIN
    NewDataTable new
    ON
    old.PlantID = new.PlantID
    AND
    old.OutletID = new.OutletID
WHERE
    (
        old.BusinessTypeID <> new.BusinessTypeID
        OR
        old.TradeChannelID <> new.TradeChannelID
    )
选择
老花
,老外
,(当old.BusinessTypeID为new.BusinessTypeID时为大小写,然后old.BusinessTypeID为END)作为BusinessTypeID
,(当old.BusinessTypeID为new.BusinessTypeID时,则为new.BusinessTypeID结束)作为Change\u BusinessTypeID
,(当old.TradeChannelID为new.TradeChannelID时,则为old.TradeChannelID结束)作为TradeChannelID
,(当old.TradeChannelID为new.TradeChannelID时,则为new.TradeChannelID结束)作为Change\u TradeChannelID
从…起
旧数据表旧
完全外接
新建数据表新建
在…上
old.PlantID=new.PlantID
及
old.OutletID=new.OutletID
哪里
(
old.BusinessTypeID new.BusinessTypeID
或
old.TradeChannelID new.TradeChannelID
)

这是一个简单的版本。您可以根据需要更改CASE语句,以获得所需的输出(例如,使用位字段等)。。。如果您希望返回所有行,无论更改与否,只需REM out
select *
 from @NewDataTable
except select *
 from @OldDataTable
--Find which records are different between the tables.
--Note, this will show duplicates only once and will not take into consideration additions to OldDataTable.
;with GetDiff as (
select PlantID , OutletId  , BusinessTypeID , TradeChannelID 
from @NewDataTable
except 
select PlantID , OutletId  , BusinessTypeID , TradeChannelID  
from @OldDataTable
)

--Join to the CTE. Note: Use a left join for OldDataTable in case a new record appears in NewDataTable
select g.PlantID, g.OutletId, n.BusinessTypeID, o.BusinessTypeID as Change_BusinessTypeID, n.TradeChannelID, o.TradeChannelID as Change_TradeChannelID
from GetDiff G
join @NewDataTable n on g.OutletId = n.OutletId
left join @OldDataTable o on g.OutletId = o.OutletId