我有一个表,它表示来自另一个表的行的整个更新历史. 例:

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 了情节.我是否可以采取一种不同的(更简单的)方法?

推荐答案

查看您的特定数据,我认为以下数据符合您所描述的标准--请注意,您所需结果的实际示例将阐明这一点,并根据您的样本数据代表您的真实数据的准确性,可能需要进行调整.注意:在你的描述中,我认为生效日期是不正确的,它看起来像02而不是03.

with seq as (
    select * , Row_Number() over(partition by primaryId order by HistoryId desc) rn
    from t
)
select v1.*, v2.*, v3.*, v4.*, v5.* 
from seq s
outer apply (
    select top(1) UpdatedBy A_UpdatedBy, UpdatedOn A_UpdatedOn from t 
    where t.PrimaryId = s.PrimaryId and t.ValA = s.ValA 
    order by t.HistoryId 
)v1
outer apply (
    select top(1) UpdatedBy B_UpdatedBy, UpdatedOn B_UpdatedOn from t 
    where t.PrimaryId = s.PrimaryId and t.ValB = s.ValB
    order by t.HistoryId 
)v2
outer apply (
    select top(1) UpdatedBy C_UpdatedBy, UpdatedOn C_UpdatedOn from t 
    where t.PrimaryId = s.PrimaryId and t.ValC = s.ValC
    order by t.HistoryId 
)v3
outer apply (
    select top(1) UpdatedBy D_UpdatedBy, UpdatedOn D_UpdatedOn from t 
    where t.PrimaryId = s.PrimaryId and t.ValD = s.ValD
    order by t.HistoryId 
)v4
outer apply (
    select top(1) UpdatedBy E_UpdatedBy, UpdatedOn E_updatedOn from t 
    where t.PrimaryId = s.PrimaryId and t.ValE = s.ValE
    order by t.HistoryId 
)v5
where rn = 1;

看到一个working demo Fiddle

Sql相关问答推荐

错误ORA-00908:通过全能自动化,缺少PLSQL编译器的关键字

需要解决办法通过传递过程参数而不是声明表行类型来声明表类型

Select 最大值,但当并列时,从其他列 Select 最大值

删除MariaDB数据库中的JSON数据

在请求结束之前,PostgreSQL不会考虑使用中的删除

如何使用WSO2将空值传递给我的SQL Server存储过程?

Lag()函数的差异:R与SQL(将R代码转换为SQL)

使用SQL创建列出两个时间戳之间小时数的列

如何为缺少的类别添加行

同时插入和更新记录

在 SQL Server 中合并两个 XML 列

snowflake中的动态文件名生成

SQL Server - 判断 ids 层次 struct 中的整数 (id)

在SQL中实现表格数据透视类型报表

计算 BigQuery 中列的中值差 - 分析函数不能作为聚合函数的参数

MariaDB非常简单的MATCHAGAINST查询不使用FULLTEXT索引吗?

根据开始时间和结束时间计算has_impact字段

使用ALTER TABLE无法删除列

批量更改WooCommerce中所有产品的税收状态

存储过程 - 动态 SQL 中不同列值的计数