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

データのスナップショットから個々の変更を抽出するクエリを作成するにはどうすればよいですか?

    UNPIVOTを使用した作業サンプルを次に示します。これは、私の質問に対する私の回答に基づいていますSQLのペアで部分的にUNPIVOTするためのより良い方法

    これにはいくつかの優れた機能があります。

    1. フィールドを追加するのは簡単です。 SELECT句とUNPIVOT句に値を追加するだけです。 UNION句を追加する必要はありません

    2. where句WHERE curr.value <> prev.value 追加されたフィールドの数に関係なく、変更されることはありません。

    3. パフォーマンスは驚くほど速いです。

    4. 必要に応じて、現在のバージョンのOracleに移植可能

    SQL

    Declare @Snapshots as table(
    Sequence int,
    DateTaken      datetime,
    [id] int,
    field1 varchar(20),
    field2 int)
    
    
    
    INSERT INTO @Snapshots VALUES 
    
          (1,    '2011-01-01',      1,     'Red',          2),
          (2,    '2011-01-01',      2,     'Blue',        10),
          (3,    '2011-02-01',      1,     'Green',        2),
          (4,    '2011-03-01',      1,     'Green' ,       3),
          (5,    '2011-03-01',      2,     'Purple',       2),
          (6,    '2011-04-01',      1,     'Yellow',       2)
    
    ;WITH Snapshots (Sequence, DateTaken, ID, Field1, Field2, _Index)
    AS
    (
        SELECT Sequence, DateTaken, ID, Field1, Field2, ROW_NUMBER() OVER (ORDER BY ID, Sequence) _Index
        FROM @Snapshots
    )
    ,  data as(
    SELECT
         c._Index
        , c.DateTaken
        ,  c.ID
        , cast(c.Field1  as varchar(max)) Field1
        , cast(p.Field1  as varchar(max))Field1_Previous
        , cast(c.Field2   as varchar(max))Field2
        , cast(p.Field2  as varchar(max)) Field2_Previous 
    
    
    FROM Snapshots c
    JOIN Snapshots p ON p.ID = c.ID AND (p._Index + 1) = c._Index
    )
    
    
    , fieldsToRows 
         AS (SELECT DateTaken, 
                    id,
                    _Index,
                    value,
                    field
    
             FROM   data p UNPIVOT (value FOR field IN (field1, field1_previous, 
                                                            field2, field2_previous) ) 
                    AS unpvt
            ) 
    SELECT 
        curr.DateTaken,
        curr.ID,
        curr.field,
        prev.value previous,
        curr.value 'current'
    
    FROM 
            fieldsToRows curr 
            INNER  JOIN  fieldsToRows prev
            ON curr.ID = prev.id
                AND curr._Index = prev._Index 
                AND curr.field + '_Previous' = prev.field
    WHERE 
        curr.value <> prev.value
    

    出力

    DateTaken               ID          field     previous current
    ----------------------- ----------- --------- -------- -------
    2011-02-01 00:00:00.000 1           Field1    Red      Green
    2011-03-01 00:00:00.000 1           Field2    2        3
    2011-04-01 00:00:00.000 1           Field1    Green    Yellow
    2011-04-01 00:00:00.000 1           Field2    3        2
    2011-03-01 00:00:00.000 2           Field1    Blue     Purple
    2011-03-01 00:00:00.000 2           Field2    10       2
    


    1. postgresqlで削除された行を取り戻しました

    2. SQLステートメントにテーブルが存在する場合は、Oracleデータベースからテーブルを削除します

    3. RHEL8にMariaDB10をインストールする方法

    4. 変更された行を検索 (NULL を含む複合キー)