SQL 服务器更新行,其中日期不是记录按某个 ID 分组时的最大日期

SQL Server Update Row where date is not the max date when records are grouped by some ID

我有一个 table 每天加载帐户记录的地方。如果一个帐户进入 table 并且它已经存在,我将这两个记录都保存在数据库中,但需要使用旧的 record_date 更新记录,将其 end_date 设置为今天。 Account_ID 是唯一的帐户标识符。 其次,如果 record_date 相同,我会保留较新的条目,可以通过 table_ID 身份字段识别。

例如

TABLE_ID,account_ID,end_date,record_date
2   28576800    NULL    2020-10-20
23  28576800    NULL    2020-10-20
20  32477400    NULL    2020-11-09
22  32477400    NULL    2020-11-13

这是加载数据时 table 的样子。

  1. 我需要更新 table_id=20 行中的 end_date,因为 table_id=22 行有更新的 record_date.
  2. 我需要更新 table_id=2 行中的 end_date 因为 record_date 是相同的所以我们结束较小的 table_ID

我试过了;

UPDATE dbo.accounts
SET END_DATE = GETUTCDATE()
where END_DATE is null
and  Record_date not in
(SELECT MAX(Record_date ) as mxrptDate
         FROM dbo.accounts
         GROUP BY account_ID)  

这没有按预期工作,因为它没有专门针对我要更新的特定 account_iD 的最大值(record_date)。

当 recrod_date 相同时,我使用相同类型的查询,我认为它有效,因为 table_id 是唯一的。不过感觉一定有更好的办法。

    UPDATE dbo.accounts
    SET END_DATE = GETUTCDATE()
    where END_DATE is null
    and  table_id not in
    (SELECT MAX(table_id ) as mxtblid
  FROM dbo.accounts
GROUP BY account_ID)  

你的第二个查询快完成了,你只需要关联子查询:

UPDATE ac
SET END_DATE = GETUTCDATE()
FROM dbo.accounts ac
where ac.END_DATE is null
  and ac.table_id <>
    (SELECT MAX(table_id) as mxtblid
      FROM dbo.accounts ac2
    WHERE ac2.account_ID = ac.account_ID)  

但我们也可以使用 window 函数来解决这个问题,而无需求助于自连接。这可能或多或少的性能,做测试。

我们可以 select 使用子查询正确的行,并直接更新这些行:

UPDATE ac
SET END_DATE = GETUTCDATE()
FROM (
    SELECT *,
        rn = ROW_NUMBER() OVER (PARTITION BY account_ID ORDER BY TABLE_ID DESC)
    FROM dbo.accounts ac
    where ac.END_DATE is null
) ac
WHERE ac.rn > 1;

编辑

看来你也想按日期排序

最终解决方案将找到最新的 record_date 或者如果有多个记录具有该日期,则取最高的 table_id:

UPDATE ac
SET END_DATE = GETUTCDATE()
FROM (
    SELECT *,
        rn = ROW_NUMBER() OVER (PARTITION BY account_ID ORDER BY record_date desc, TABLE_ID DESC)
    FROM dbo.accounts ac
    where ac.END_DATE is null
) ac
WHERE ac.rn > 1;