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
相关产品推荐
相关产品推荐

