You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SCD Type2场景下如何匹配行复制日期:SQL设置新许可start_date为旧许可end_date加1

提问内容

我一直尝试编写SQL查询实现将公司新许可方案的start_date设为该公司上一许可方案的expiration date/end_date加1天,目前遇到了阻碍。

您可以通过下图更清晰地了解我的需求:(需求示意图已省略)

我目前已尝试的写法如下:

Update dbo.license_case_study
Set start_date = [Expiration date]
where [Product service state] = 'active' and [Company ID] = [Company ID] and start_date is not null

上述查询明显存在缺陷,尤其是[Company ID] = [Company ID]这部分逻辑。我不确定如何将公司上一个许可方案的expiration date/end_date复制到同公司新许可方案的对应位置,写[Company ID] = [Company ID]的初衷是匹配同公司的两行数据,避免end_date被错误复制到其他公司的新许可方案中。

该操作需要覆盖所有有新激活许可方案的公司,将已终止许可方案的expiration date/end_date复制到同公司的激活许可方案对应字段,而不是仅适用于单个公司。请问我是否应该用MERGE代替UPDATE来实现需求?

非常感谢大家帮忙解答这个问题,如有需要我可以随时提供更多细节。

祝好
Axel


解决方案

不需要使用MERGE,用带自关联的UPDATE语句即可实现需求,从表名前缀dbo.判断你使用的是SQL Server环境,适配写法如下:

UPDATE active_license
-- 不需要加1天的话直接去掉DATEADD函数,写为 = expired_license.[Expiration date]
SET start_date = DATEADD(day, 1, expired_license.[Expiration date])
FROM dbo.license_case_study active_license
-- 关联同公司的已终止许可,用别名区分两张表避免匹配逻辑混乱
INNER JOIN dbo.license_case_study expired_license
  ON active_license.[Company ID] = expired_license.[Company ID]
  AND expired_license.[Product service state] != 'active'
WHERE active_license.[Product service state] = 'active'
  -- 只更新还没赋值start_date的激活许可,可根据业务需求调整该条件
  AND active_license.start_date IS NULL
  -- 同公司有多个历史终止许可时,只取最新的过期时间匹配
  AND expired_license.[Expiration date] = (
    SELECT MAX([Expiration date])
    FROM dbo.license_case_study
    WHERE [Company ID] = active_license.[Company ID]
      AND [Product service state] != 'active'
)

注意:执行UPDATE前建议先运行下面的SELECT语句验证匹配结果是否符合预期,避免误改数据:

SELECT 
  active_license.[Company ID],
  active_license.id as 激活许可ID,
  expired_license.[Expiration date] as 上一许可过期时间,
  DATEADD(day, 1, expired_license.[Expiration date]) as 待设置的新start_date
FROM dbo.license_case_study active_license
INNER JOIN dbo.license_case_study expired_license
  ON active_license.[Company ID] = expired_license.[Company ID]
  AND expired_license.[Product service state] != 'active'
WHERE active_license.[Product service state] = 'active'
  AND active_license.start_date IS NULL
  AND expired_license.[Expiration date] = (
    SELECT MAX([Expiration date])
    FROM dbo.license_case_study
    WHERE [Company ID] = active_license.[Company ID]
      AND [Product service state] != 'active'
)

如果你使用的是MySQL环境,写法调整如下:

UPDATE license_case_study active_license
INNER JOIN (
    SELECT `Company ID`, MAX(`Expiration date`) as latest_expired
    FROM license_case_study
    WHERE `Product service state` != 'active'
    GROUP BY `Company ID`
) expired_license ON active_license.`Company ID` = expired_license.`Company ID`
SET active_license.start_date = DATE_ADD(expired_license.latest_expired, INTERVAL 1 DAY)
WHERE active_license.`Product service state` = 'active'
AND active_license.start_date IS NULL

内容的提问来源于stack exchange,提问作者A A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:45:04