查询显示另一个 table 的旧值和新值 - 查询最新的 ChangeDate
Query to show old and new values from another table - query the latest ChangeDate
我在 SQL Server 2012 中有 3 个表。
Table历史是对TableA中的值所做的所有更改的历史。它可以对PRICE,LOT,INTEREST进行许多更改,但在大多数情况下该值是只改过一次。
Table一个
AID PRICE LOT INTEREST
------------------------
1 1500 9000 0.5
2 2500 20 1.5
Table B
BID AID
--------
11 1
22 2
Table历史
BID ChangeField OldValue NewValue ChangeDate
------------------------------------------------------------
11 PRICE 1700 1500 1/1/22
11 LOT 10000 8000 12/15/21
11 LOT 8000 9000 2/2/22
我需要一个查询来显示 Table A 以及 Table 历史记录中的旧值和新值。如果有超过 1 个更改,则对于旧值,获取最近的先前值。在上面的示例中,Lot 最近的先前值是 2/2/22 的 8000(不是 12/15/21 的 10000)。
示例:
AID OldPRICE NewPRICE OldLot NewLot OldInterest NewInterest
----------------------------------------------------------------
1 1700 1500 8000 9000 0.5 0.5
2 2500 2500 20 20 1.5 1.5
本次查询returnsOldLot = 10000(Lot的最大值),而不是8000(最近的先前值)
SELECT A.AID,
MAX(CONVERT(numeric(30, 2),ISNULL(CASE WHEN h.ChangeField = 'LOT' THEN h.OldValue
END,A.LOT))) OldLot,
MAX(CONVERT(numeric(30, 2),ISNULL(CASE WHEN h.ChangeField = 'LOT' THEN h.NewValue
END,A.LOT))) NewLot
FROM A
LEFT JOIN B ON A.AID = B.AID
LEFT JOIN History h ON B.BID = h.BID
WHERE H.BID = 11
GROUP BY A.AID
下面那个returns(注意OldLot = 10000而不是8000)
AID OldLot NewLot
--------------------
1 10000 9000
谢谢
如果我正确理解你的要求,你就在每个字段的最新历史值之后,你可以使用 row_number 分区,然后你只需要将行转换为列以与当前值:
with h as (
select b.aid, h.*,
Row_Number() over(partition by h.bid, h.changefield order by h.changedate desc) rn
from history h
join b on b.bid=h.bid
)
select a.aid,
isnull(h.oldprice, a.price) OldPrice, a.PRICE newprice,
isnull(h.oldLot, a.lot) OldLot, a.Lot NewLot,
isnull(h.oldInterest, a.interest) OldInterest, a.Interest newInterest
from a
outer apply (
select
max(case when changefield = 'LOT' then oldvalue end) OldLot,
max(case when changefield = 'PRICE' then oldvalue end) OldPrice,
max(case when changefield = 'INTEREST' then oldvalue end) OldInterest
from h
where h.aid = a.aid and h.rn = 1
)h
另请注意,如果您使用的是更新版本的 SQL 服务器 (2016+),则使用 系统版本控制 及其自身扩展的内置功能到 t-sql 这种查询。
我在 SQL Server 2012 中有 3 个表。
Table历史是对TableA中的值所做的所有更改的历史。它可以对PRICE,LOT,INTEREST进行许多更改,但在大多数情况下该值是只改过一次。
Table一个
AID PRICE LOT INTEREST
------------------------
1 1500 9000 0.5
2 2500 20 1.5
Table B
BID AID
--------
11 1
22 2
Table历史
BID ChangeField OldValue NewValue ChangeDate
------------------------------------------------------------
11 PRICE 1700 1500 1/1/22
11 LOT 10000 8000 12/15/21
11 LOT 8000 9000 2/2/22
我需要一个查询来显示 Table A 以及 Table 历史记录中的旧值和新值。如果有超过 1 个更改,则对于旧值,获取最近的先前值。在上面的示例中,Lot 最近的先前值是 2/2/22 的 8000(不是 12/15/21 的 10000)。
示例:
AID OldPRICE NewPRICE OldLot NewLot OldInterest NewInterest
----------------------------------------------------------------
1 1700 1500 8000 9000 0.5 0.5
2 2500 2500 20 20 1.5 1.5
本次查询returnsOldLot = 10000(Lot的最大值),而不是8000(最近的先前值)
SELECT A.AID,
MAX(CONVERT(numeric(30, 2),ISNULL(CASE WHEN h.ChangeField = 'LOT' THEN h.OldValue
END,A.LOT))) OldLot,
MAX(CONVERT(numeric(30, 2),ISNULL(CASE WHEN h.ChangeField = 'LOT' THEN h.NewValue
END,A.LOT))) NewLot
FROM A
LEFT JOIN B ON A.AID = B.AID
LEFT JOIN History h ON B.BID = h.BID
WHERE H.BID = 11
GROUP BY A.AID
下面那个returns(注意OldLot = 10000而不是8000)
AID OldLot NewLot
--------------------
1 10000 9000
谢谢
如果我正确理解你的要求,你就在每个字段的最新历史值之后,你可以使用 row_number 分区,然后你只需要将行转换为列以与当前值:
with h as (
select b.aid, h.*,
Row_Number() over(partition by h.bid, h.changefield order by h.changedate desc) rn
from history h
join b on b.bid=h.bid
)
select a.aid,
isnull(h.oldprice, a.price) OldPrice, a.PRICE newprice,
isnull(h.oldLot, a.lot) OldLot, a.Lot NewLot,
isnull(h.oldInterest, a.interest) OldInterest, a.Interest newInterest
from a
outer apply (
select
max(case when changefield = 'LOT' then oldvalue end) OldLot,
max(case when changefield = 'PRICE' then oldvalue end) OldPrice,
max(case when changefield = 'INTEREST' then oldvalue end) OldInterest
from h
where h.aid = a.aid and h.rn = 1
)h
另请注意,如果您使用的是更新版本的 SQL 服务器 (2016+),则使用 系统版本控制 及其自身扩展的内置功能到 t-sql 这种查询。