2016-01-19 18 views
1

鑑於下表,我想獲取fruit的每個值的兩列priceqty的更改歷史記錄。我使用MS SQL Server 2012的跟蹤T-SQL中每個表列的數據更改

因此,例如:

  • 行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 | 
+----+----+--------+--------+--------+---------+ 

回答

4

這裏有一種方法:

;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 

Demo here

+0

這是如何表現明智? – rickythefox

+0

@rickythefox您可以嘗試兩種解決方案,並告訴我們他們如何執行您的實際數據。 –

1

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

第一步是找到更改。你可以通過給id排序的相同水果的所有記錄進行編號,然後加入後續記錄來完成此操作。然後你可以將UNPIVOT的結果和過濾器無變化列出。

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的情況是不可避免的。

+0

感謝您的回答! – rickythefox