我有一张这样的表:
CREATE TABLE AuditTrail
(
AuditTrailId Integer,
OldValue xml,
NewValue xml
)
INSERT INTO **AuditTrail**
SELECT 107 AS AuditTrailId,
'<Root><NHL_DARCR><NHLLoanId>750</NHLLoanId><Amount>909.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-01T18:19:49.700</ModifiedDate></NHL_DARCR><NHL_DARCR><NHLLoanId>77</NHLLoanId><Amount>404.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:32:52.137</ModifiedDate></NHL_DARCR></Root>' AS OldValue,
'<Root><NHL_DARCR><NHLLoanId>750</NHLLoanId><Amount>101.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:33:22.447</ModifiedDate></NHL_DARCR><NHL_DARCR><NHLLoanId>77</NHLLoanId><Amount>303.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:33:22.447</ModifiedDate></NHL_DARCR></Root>' AS NewValue
我要求的输出应该是:
AuditTrailId Column_Name Old_Value New_Value
------------ ------------ -------------------------------------------------- --------------------------------------------------
107 NHLLoanId 77 77
107 Amount 404.00 303.00
107 ModifiedBy 2001 2001
107 ModifiedDate 2018-02-02T09:32:52.137 2018-02-02T09:33:22.447
107 NHLLoanId 750 750
107 Amount 909.00 101.00
107 ModifiedBy 2001 2001
107 ModifiedDate 2018-02-01T18:19:49.700 2018-02-02T09:33:22.447
为了得到上面提到的输出,我最终尝试了这个:
SELECT DISTINCT
AuditIdOld
, C2_Old AS Column_Name
, ISNULL(C3_Old, '-') Old_Value
, ISNULL(C3_New, '-') New_Value
FROM
(
SELECT distinct
AuditTrailId AuditIdOld
, x.value('local-name(..)', 'varchar(50)') AS C1_Old
, x.value('local-name(.)', 'varchar(50)') AS C2_Old
, x.value('.', 'varchar(max)') AS C3_Old
, x.value('(text())[1]','varchar(32)') as xNHLLoanID
FROM AuditTrail
CROSS APPLY OldValue.nodes('Root//*') e(x)
WHERE oldvalue IS NOT NULL
AND x.value('local-name(..)', 'varchar(50)') <> 'Root'
) t1
JOIN
(
SELECT DISTINCT AuditTrailId AuditIdNew
, x.value('local-name(..)'
, 'varchar(50)') AS C1_New, x.value('local-name(.)'
, 'varchar(50)') AS C2_New, x.value('.',
'varchar(max)') AS C3_New
, x.value('(text())[1]','varchar(32)') as xNHLLoanID
FROM AuditTrail
CROSS APPLY NewValue.nodes('Root//*') e(x)
WHERE NewValue IS NOT NULL
AND x.value('local-name(..)', 'varchar(50)') <> 'Root'
) t2
ON AuditIdOld = AuditIdNew
and t1.C2_Old = t2.C2_New
仍然没有得到所需的输出。任何人都可以帮我解决问题吗?
答案 0 :(得分:3)
这是我的解决方案,但这只是基于我们这里的小数据。我猜想还有很多,而且我不知道它是否适用于所有内容(例如,你可能有更多的字段,我没有将它们包含在VALUES
的字段CTE中(因为我不知道他们是什么))。
如果您对它正在做什么有任何疑问,我很乐意回答它们,但您需要支持您需要做的任何更改:
USE Sandbox;
GO
CREATE TABLE AuditTrail (AuditTrailId int,
OldValue xml,
NewValue xml);
GO
INSERT INTO AuditTrail
SELECT 107 AS AuditTrailId,
'<Root><NHL_DARCR><NHLLoanId>750</NHLLoanId><Amount>909.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-01T18:19:49.700</ModifiedDate></NHL_DARCR><NHL_DARCR><NHLLoanId>77</NHLLoanId><Amount>404.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:32:52.137</ModifiedDate></NHL_DARCR></Root>' AS OldValue,
'<Root><NHL_DARCR><NHLLoanId>750</NHLLoanId><Amount>101.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:33:22.447</ModifiedDate></NHL_DARCR><NHL_DARCR><NHLLoanId>77</NHLLoanId><Amount>303.00</Amount><ModifiedBy>2001</ModifiedBy><ModifiedDate>2018-02-02T09:33:22.447</ModifiedDate></NHL_DARCR></Root>' AS NewValue;
GO
WITH Fields AS (
SELECT *
FROM (VALUES ('NHLLoanId',1),('Amount',2),('ModifiedBy',3),('ModifiedDate',4)) V(FieldName, SortOrder)),
OldValues AS (
SELECT A.AuditTrailId,
OV.D.value('(NHLLoanId/text())[1]','varchar(50)') AS NHLLoadId,
OV.D.value('(Amount/text())[1]','varchar(50)') AS Amount,
OV.D.value('(ModifiedBy/text())[1]','varchar(50)') AS ModifiedBy,
OV.D.value('(ModifiedDate/text())[1]','varchar(50)') AS ModifiedDate
FROM AuditTrail A
CROSS APPLY A.OldValue.nodes('/Root/NHL_DARCR') OV(D)),
NewValues AS(
SELECT A.AuditTrailId,
NV.D.value('(NHLLoanId/text())[1]','varchar(50)') AS NHLLoadId,
NV.D.value('(Amount/text())[1]','varchar(50)') AS Amount,
NV.D.value('(ModifiedBy/text())[1]','varchar(50)') AS ModifiedBy,
NV.D.value('(ModifiedDate/text())[1]','varchar(50)') AS ModifiedDate
FROM AuditTrail A
CROSS APPLY A.NewValue.nodes('/Root/NHL_DARCR') NV(D)),
OldUnPivot AS(
SELECT OV.AuditTrailId,
F.FieldName AS Column_Name,
F.SortOrder,
OV.NHLLoadId,
CASE F.FieldName WHEN 'NHLLoanId' THEN OV.NHLLoadId
WHEN 'Amount' THEN OV.Amount
WHEN 'ModifiedBy' THEN OV.ModifiedBy
WHEN 'ModifiedDate' THEN OV.ModifiedDate END AS Old_Value
FROM Fields F
CROSS JOIN OldValues OV),
NewUnPivot AS(
SELECT NV.AuditTrailId,
F.FieldName AS Column_Name,
F.SortOrder,
NV.NHLLoadId,
CASE F.FieldName WHEN 'NHLLoanId' THEN NV.NHLLoadId
WHEN 'Amount' THEN NV.Amount
WHEN 'ModifiedBy' THEN NV.ModifiedBy
WHEN 'ModifiedDate' THEN NV.ModifiedDate END AS New_Value
FROM Fields F
CROSS JOIN NewValues NV)
SELECT OUP.AuditTrailId,
OUP.Column_Name,
OUP.Old_Value,
NUP.New_Value
FROM OldUnPivot OUP
JOIN NewUnPivot NUP ON OUP.AuditTrailId = NUP.AuditTrailId
AND OUP.NHLLoadId = NUP.NHLLoadId
AND OUP.Column_Name = NUP.Column_Name
WHERE OUP.Column_Name IS NOT NULL
ORDER BY AuditTrailID ASC,
OUP.NHLLoadId DESC,
OUP.SortOrder ASC;
GO
DROP TABLE AuditTrail;