Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bagaimana saya bisa menulis kueri untuk mengekstrak perubahan individual dari snapshot data?

Berikut adalah contoh kerja yang menggunakan UNPIVOT. Ini didasarkan pada jawaban saya untuk pertanyaan saya Cara yang lebih baik untuk UNPIVOT Sebagian dalam Pasangan di SQL

Ini memiliki beberapa fitur bagus.

  1. Menambahkan bidang tambahan itu mudah. Cukup tambahkan nilai ke klausa SELECT dan UNPIVOT. Anda tidak perlu menambahkan klausa UNION tambahan

  2. Klausa where WHERE curr.value <> prev.value tidak pernah berubah terlepas dari berapa banyak bidang yang ditambahkan.

  3. Performanya sangat cepat.

  4. Portabel ke versi Oracle saat ini jika Anda membutuhkannya

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

Keluaran

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara membuat batasan pemeriksaan beberapa tabel?

  2. Bagaimana Fungsi QUOTENAME() Bekerja di SQL Server (T-SQL)

  3. Kesalahan konversi data beban massal (pemotongan)

  4. Pengoptimalan kinerja XML Server XML

  5. Menyimpan Tipe Data Biner di SQL Server