sql >> データベース >  >> RDS >> Sqlserver

SQL:各列のレコードの監査を返す

    何も見逃していなければ:

    WITH ranked AS (
      SELECT
        ChangeDate,
        ColPK,
        Col1,
        Col2,
        Col3,
        Col4,
        Col5,
        OverallRank = ROW_NUMBER() OVER (PARTITION BY ColPK       ORDER BY ChangeDate),
        Col1Rank    = ROW_NUMBER() OVER (PARTITION BY ColPK, Col1 ORDER BY ChangeDate),
        Col2Rank    = ROW_NUMBER() OVER (PARTITION BY ColPK, Col2 ORDER BY ChangeDate),
        Col3Rank    = ROW_NUMBER() OVER (PARTITION BY ColPK, Col3 ORDER BY ChangeDate),
        Col4Rank    = ROW_NUMBER() OVER (PARTITION BY ColPK, Col4 ORDER BY ChangeDate),
        Col5Rank    = ROW_NUMBER() OVER (PARTITION BY ColPK, Col5 ORDER BY ChangeDate)
      FROM AuditTable
    )
    , ranked2 AS (
      SELECT
        ChangeDate,
        ColPK,
        Col1,
        Col2,
        Col3,
        Col4,
        Col5,
        Col1Group = RANK() OVER (PARTITION BY ColPK, Col1 ORDER BY OverallRank - Col1Rank),
        Col2Group = RANK() OVER (PARTITION BY ColPK, Col2 ORDER BY OverallRank - Col2Rank),
        Col3Group = RANK() OVER (PARTITION BY ColPK, Col3 ORDER BY OverallRank - Col3Rank),
        Col4Group = RANK() OVER (PARTITION BY ColPK, Col4 ORDER BY OverallRank - Col4Rank),
        Col5Group = RANK() OVER (PARTITION BY ColPK, Col5 ORDER BY OverallRank - Col5Rank),
        Col1Rank = ROW_NUMBER() OVER (PARTITION BY ColPK, Col1, OverallRank - Col1Rank ORDER BY ChangeDate),
        Col2Rank = ROW_NUMBER() OVER (PARTITION BY ColPK, Col2, OverallRank - Col2Rank ORDER BY ChangeDate),
        Col3Rank = ROW_NUMBER() OVER (PARTITION BY ColPK, Col3, OverallRank - Col3Rank ORDER BY ChangeDate),
        Col4Rank = ROW_NUMBER() OVER (PARTITION BY ColPK, Col4, OverallRank - Col4Rank ORDER BY ChangeDate),
        Col5Rank = ROW_NUMBER() OVER (PARTITION BY ColPK, Col5, OverallRank - Col5Rank ORDER BY ChangeDate)
      FROM ranked
    ),
    unpivoted AS (
      SELECT
        r.ChangeTime,
        r.ColPK,
        x.ColName,
        ColRank = CASE x.Colname
          WHEN 'Col1' THEN Col1Group
          WHEN 'Col2' THEN Col2Group
          WHEN 'Col3' THEN Col3Group
          WHEN 'Col4' THEN Col4Group
          WHEN 'Col5' THEN Col5Group
        END,
        Value = CASE x.Colname
          WHEN 'Col1' THEN CONVERT(nvarchar(100), r.Col1)
          WHEN 'Col2' THEN CONVERT(nvarchar(100), r.Col2)
          WHEN 'Col3' THEN CONVERT(nvarchar(100), r.Col3)
          WHEN 'Col4' THEN CONVERT(nvarchar(100), r.Col4)
          WHEN 'Col5' THEN CONVERT(nvarchar(100), r.Col5)
        END
      FROM ranked2 r
        INNER JOIN (VALUES ('Col1'), ('Col2'), ('Col3'), ('Col4'), ('Col5')) x (ColName)
          ON x.ColName = 'Col1' AND Col1Rank = 1
          OR x.ColName = 'Col2' AND Col2Rank = 1
          OR x.ColName = 'Col3' AND Col3Rank = 1
          OR x.ColName = 'Col4' AND Col4Rank = 1
          OR x.ColName = 'Col5' AND Col5Rank = 1
    )
    SELECT
      new.ChangeTime,
      new.ColPK,
      new.ColName,
      old.Value AS OldValue,
      new.Value AS NewValue
    FROM unpivoted new
      LEFT JOIN unpivoted old
        ON new.ColPK   = old.ColPK
       AND new.ColName = old.ColName
       AND new.ColRank = old.ColRank + 1
    

    基本的には、同じ値の連続するグループをランク付けし、すべての値の最初の出現を選択するという考え方です。これは、値が監査されているすべての列に対して行われ、その過程で列のピボットが解除されます。その後、ピボットされていない行セットがそれ自体に結合されます。つまり、すべての PK および列名について、すべての行が (ランキングに基づいて) 前の行と照合され、最終的な結果セットの同じ行の古い値が取得されます。



    1. Mysql localhost!=127.0.0.1?

    2. XML でノードの値を合計するときの SQL Server の奇妙な動作

    3. mysqlの現在の時刻とそのタイムゾーンのnow()を理解するのに役立ちます

    4. groupby句を使用したSQL更新クエリ