根据下表,我想获取price
的每个值的两列qty
和fruit
的更改历史记录。我使用的是MS SQL Server 2012。
例如:
有办法做到这一点吗?还有办法有效地做到这一点吗?
来源表
+----+---------+--------+--------+---------+
| 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 |
+----+----+--------+--------+--------+---------+
答案 0 :(得分: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
答案 1 :(得分:1)
以下答案的前提条件是price
和qty
具有相同的数据类型,而id
是IDENTITY
列。
第一步是找到变化。您可以通过数字化由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
中的案例是不可避免的。