我有一个表,它表示来自另一个表的行的整个更新历史. 例:
HistoryId | PrimaryId | ValA | ValB | ValC | ValD | ValE | UpdatedBy | UpdatedOn |
---|---|---|---|---|---|---|---|---|
4 | 56 | 100 | 20 | 50 | 50 | NULL | david | 1/4/2024 |
3 | 56 | 100 | 30 | 50 | 50 | NULL | cameron | 1/3/2024 |
2 | 56 | 50 | 30 | 50 | 50 | NULL | bob | 1/2/2024 |
1 | 56 | 50 | 40 | 25 | 50 | NULL | alice | 1/1/2024 |
在本例中,最后一个更新Vald的人是Alice on 1/1,因为值在她输入之后没有更改.卡梅隆在1/3改变了Vala,David在1/4改变了ValB,Bob在1/3改变了Valc.Vale从来没有空以外的值,因此从未更新过.
如何获得最后一个更新行中每个值的人的列表以及更新时间?我试过慢性创伤性脑炎
WITH _valA AS
(
SELECT
PrimaryId, ValA, UpdatedBy, UpdatedOn,
ROW_NUMBER() OVER (ORDER BY PrimaryId, UpdatedOn) AS RowNo
FROM
table
WHERE
PrimaryId = @PrimaryId
AND HistoryId >= (SELECT TOP 1 HistoryId FROM table
WHERE PrimaryId = @PrimaryId
AND ValA != NULL
ORDER BY HistoryId)
),
_aMax AS
(
SELECT
s.PrimaryId, MAX(s.UpdatedOn) AS UpdatedOn
FROM
_valA s
LEFT JOIN
_valA p ON p.PrimaryId = s.PrimaryId
AND p.RowNo + 1 = s.RowNo
WHERE
p._valA != s._valA
GROUP BY
s.PrimaryId
),
_valB AS
(
SELECT
PrimaryId, ValB, UpdatedBy, UpdatedOn,
ROW_NUMBER() OVER (ORDER BY PrimaryId, UpdatedOn) AS RowNo
FROM
table
WHERE
PrimaryId = @PrimaryId
AND HistoryId >= (SELECT TOP 1 HistoryId FROM table
WHERE PrimaryId = @PrimaryId
AND ValB != NULL
ORDER BY HistoryId)
),
_bMax AS
(
SELECT
s.PrimaryId, MAX(s.UpdatedOn) AS UpdatedOn
FROM
_valB s
LEFT JOIN
_valB p ON p.PrimaryId = s.PrimaryId
AND p.RowNo + 1 = s.RowNo
WHERE
p._valB != s._valB
GROUP BY
s.PrimaryId
),
SELECT
a.UpdatedOn AS ValAUpdatedOn,
a.UpdatedBy AS ValAUpdatedBy,
b.UpdatedOn AS ValBUpdatedOn,
b.UpdatedBy AS ValBUpdatedBy
FROM
_valA a
JOIN
_aMax am ON am.PrimaryId = a.PrimaryId
AND am.UpdatedOn = a.UpdatedOn
JOIN
_valB b ON b.PrimaryId = a.PrimaryId
JOIN
_bMax bm ON bm.PrimaryId = b.PrimaryId
AND bm.UpdatedOn = b.UpdatedOn
其中PrimaryId
链接到另一个表的主键,所以我们可以在这里看到第56行的历史.historyid = check旨在删除值历史中所有null的初始实例.一旦存在第一个非空值,就认为输入了值.如果该值后来被设置回null,这被认为是一个实质性的变化,我们确实关心这一点.
我遇到的问题包括,如果值始终为NULL,则_Vala CTE将有0行,在这种情况下,我希望为日期和用户更新返回NULL.我返回这些值的方式使这变得不可能.
此外,当我返回多个值时,从_valB到_Vala的连接在某种程度上是不好的,我很难描述它,但我知道它是错误的.
在我的实际解决方案中,我试图返回从A到E的所有值,为了简洁起见,我只是将其停在B处.
我可能完全偏离了我的解决方案的轨道,但我已经关注了一段时间,我开始失go 了情节.我是否可以采取一种不同的(更简单的)方法?