簡體   English   中英

跟蹤T-SQL中每個表列的數據更改

[英]Tracking data changes per table column in T-SQL

給定下表,我想獲取兩列price和每個fruit值的qty變化的歷史記錄。 我正在使用MS SQL Server 2012。

因此,例如:

  • 第1行和第3行之間的變化是蘋果的價格從10升至30,這在下面的結果表中給出了第1行。
  • 第2行和第4行之間的變化是,香蕉的價格從20變為30,數量從2變為3,這在結果表中給出了第2和3行。

有沒有辦法做到這一點? 有沒有辦法有效地做到這一點?

源表

+----+---------+--------+--------+---------+
| id | fruit   | price  | qty    | created |
+----+---------+--------+--------+---------+
| 1  | apples  | 10     | 1      | 1/1/16  |
+----+---------+--------+--------+---------+
| 2  | bananas | 20     | 2      | 1/1/16  |
+----+---------+--------+--------+---------+
| 3  | apples  | 30     | 1      | 2/1/16  |
+----+---------+--------+--------+---------+
| 4  | bananas | 30     | 3      | 2/1/16  |
+----+---------+--------+--------+---------+
| 5  | apples  | 30     | 2      | 3/1/16  |
+----+---------+--------+--------+---------+
| 6  | apples  | 30     | 3      | 7/1/16  |
+----+---------+--------+--------+---------+

結果表

+----+----+--------+--------+--------+---------+
| id | fk | col    | oldval | newval | changed |
+----+----+--------+--------+--------+---------+
| 1  | 3  | price  | 10     | 30     | 2/1/16  |
+----+----+--------+--------+--------+---------+
| 2  | 4  | price  | 20     | 30     | 2/1/16  |
+----+----+--------+--------+--------+---------+
| 3  | 4  | qty    | 2      | 3      | 2/1/16  |
+----+----+--------+--------+--------+---------+
| 4  | 5  | qty    | 1      | 2      | 3/1/16  |
+----+----+--------+--------+--------+---------+
| 5  | 6  | qty    | 2      | 3      | 7/1/16  |
+----+----+--------+--------+--------+---------+

這是一種方法:

;WITH LagCTE AS (
  SELECT  id, fruit, price, qty, created,
          LAG(price) OVER (PARTITION BY fruit 
                           ORDER BY created) AS prevPrice,
          LAG(qty) OVER (PARTITION BY fruit 
                         ORDER BY created) AS prevQty
  FROM mytable
)
SELECT ROW_NUMBER() OVER (ORDER BY changed) AS id,
       fk, col, oldval, newval, changed
FROM (       
  SELECT id AS fk, fruit, 'price' AS col, 
         prevPrice AS oldval, price AS newval, 
         created AS changed
  FROM LagCTE
  WHERE prevPrice <> price

  UNION ALL 

  SELECT id AS fk, fruit, 'qty' AS col, 
         prevQty AS oldval, qty AS newval, 
         created AS changed
  FROM LagCTE
  WHERE prevQty <> qty) AS t

在這里演示

以下答案的前提條件是priceqty具有相同的數據類型,並且idIDENTITY列。

第一步是找到更改。 您可以通過對id排序的同一水果的所有記錄進行id ,然后加入后續記錄來做到這一點。 然后,你可以UNPIVOT結果,並進行過濾不變colums。

WITH
   SourceNumbered AS
      (
         SELECT
               ROW_NUMBER() OVER(PARTITION BY fruit ORDER BY id) AS nr,
               id, fruit, price, qty, created
            FROM
               SourceTable
      ),
   SourceUnpivoted AS
      (
         SELECT
               U.id, U.fk, U.col
            FROM
               (
                  SELECT
                        L.id, R.id AS fk,
                        L.price - R.price AS price,
                        L.qty - R.qty AS qty
                     FROM
                        SourceNumbered L
                        INNER JOIN SourceNumbered R
                           ON R.fruit = L.fruit
                              AND R.nr = L.nr + 1
               ) D
            UNPIVOT (value FOR col IN (price, qty)) U
            WHERE
               value != 0
      )
SELECT
      U.id, U.fk, U.col,
      CASE U.col
         WHEN 'price'
            THEN O.price
         WHEN 'qty'
            THEN O.qty
      END AS oldval,
      CASE U.col
         WHEN 'price'
            THEN N.price
         WHEN 'qty'
            THEN N.qty
      END AS oldval,
      N.created AS changed
   FROM
      SourceUnpivoted U
      INNER JOIN SourceTable O
         ON O.id = U.id
      INNER JOIN SourceTable N
         ON N.id = U.fk;

由於您不能取消旋轉多於一列,因此最終SELECT情況不可避免。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM