应该对sql查询进行哪些更改才能获得上述输出?

时间:2018-02-02 08:49:41

标签: sql sql-server sql-server-2008

我有一张这样的表:

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

仍然没有得到所需的输出。任何人都可以帮我解决问题吗?

1 个答案:

答案 0 :(得分:3)

老实说,这很麻烦。它涉及数据的解析和xml解析。

这是我的解决方案,但这只是基于我们这里的小数据。我猜想还有很多,而且我不知道它是否适用于所有内容(例如,你可能有更多的字段,我没有将它们包含在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;