SQL SELECT语句优化:修复保单注销时分期状态匹配错误
问题根因
现有查询的过滤逻辑存在设计缺陷:仅按REPORTED_DATE的自然月份分组取同月份下LOAD_DATE最大的记录,完全没有处理注销记录的REPORTED_DATE早于最后一笔有效分期REPORTED_DATE的跨月场景,直接把注销状态归属到了注销记录自身的REPORTED_DATE月份(示例中为2022年5月),而不是最后一笔有效分期所在的月份(示例中为2022年6月),最终返回结果和业务要求不符。
修改方案
- 先按
LOAD_DATE倒序为同一保单的所有记录排序,识别出状态为Cancelled的注销记录,同时定位到该注销记录之前、LOAD_DATE最大的有效Active记录(即需要被注销冲抵的最后一笔分期) - 调整记录的报告月归属规则:
- 注销状态的归属月份为对应最后一笔有效分期的REPORTED_DATE所在月份,而非注销记录自身的REPORTED_DATE月份
- 注销记录REPORTED_DATE到最后一笔有效分期REPORTED_DATE之间的月份,正常取对应月份下
LOAD_DATE最大的Active记录
- 替换原有「同REPORTED月份取最大LOAD_DATE」的过滤逻辑,避免注销记录跨月错误归属。
修正后的查询语句
WITH PolicyRecordRank AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY POLICY_HKEY ORDER BY LOAD_DATE DESC) AS rn, MAX(CASE WHEN BUSINESS_STATE = 'Cancelled' THEN 1 ELSE 0 END) OVER (PARTITION BY POLICY_HKEY) AS has_cancelled, MAX(CASE WHEN BUSINESS_STATE = 'Active' THEN DATEADD(month, DATEDIFF(month, 0, REPORTED_DATE), 0) END) OVER (PARTITION BY POLICY_HKEY) AS last_active_month, MAX(CASE WHEN BUSINESS_STATE = 'Cancelled' THEN DATEADD(month, DATEDIFF(month, 0, REPORTED_DATE), 0) END) OVER (PARTITION BY POLICY_HKEY) AS cancel_report_month FROM IMPL.POLICY_SAT ), ValidPolicyRecord AS ( SELECT t.*, CASE WHEN t.BUSINESS_STATE = 'Cancelled' THEN t.last_active_month WHEN t.BUSINESS_STATE = 'Active' AND DATEADD(month, DATEDIFF(month, 0, t.REPORTED_DATE), 0) >= t.cancel_report_month THEN DATEADD(month, DATEDIFF(month, 0, t.REPORTED_DATE), 0) ELSE DATEADD(month, DATEDIFF(month, 0, t.REPORTED_DATE), 0) END AS EFFECTIVE_REPORT_MONTH FROM PolicyRecordRank t WHERE NOT ( t.has_cancelled = 1 AND t.BUSINESS_STATE = 'Cancelled' AND DATEADD(month, DATEDIFF(month, 0, t.REPORTED_DATE), 0) = t.cancel_report_month ) ), FinalRecordPerMonth AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY POLICY_HKEY, EFFECTIVE_REPORT_MONTH ORDER BY LOAD_DATE DESC) AS month_rn FROM ValidPolicyRecord ) SELECT DISTINCT f.EFFECTIVE_REPORT_MONTH AS REPORTED_DATE, f.BUSINESS_STATE, f.CREDIT_INITIAL_VALUE, f.OUTSTANDING_AMOUNT, f.INSURANCE_PREMIUM, f.LOAN_INSTALMENT_AMOUNT, f.PREMIUM_BASE, f.PREMIUM_RATE, premiumSat.CURRENCY_CODE FROM POLICY_HUB policyHub INNER JOIN POLICY_SAT_LATEST policySat ON policySat.POLICY_HKEY = policyHub.POLICY_HKEY INNER JOIN FinalRecordPerMonth f ON f.POLICY_HKEY = policyHub.POLICY_HKEY AND f.month_rn = 1 INNER JOIN ITEM_LINK itemLink ON policyHub.POLICY_HKEY = itemLink.POLICY_HKEY INNER JOIN ITEM_SAT itemSat ON itemLink.ITEM_HKEY = itemSat.ITEM_HKEY INNER JOIN PREMIUM_SAT premiumSat ON itemLink.ITEM_HKEY = premiumSat.PREMIUM_HKEY AND premiumSat.LOAD_DATE = f.LOAD_DATE WHERE policyHub.DOCUMENT_NUMBER = '111' AND f.EFFECTIVE_REPORT_MONTH BETWEEN DATEADD(month, DATEDIFF(month, 0, cast('2021-06-01T00:00:00' AS DATE)), 0) AND DATEADD(month, DATEDIFF(month, 0, cast('2022-06-30T00:00:00' AS DATE)), 0)
验证结果
基于提供的示例数据执行修正后的查询,可得到符合预期的结果:
- 2022年5月返回
Active状态,对应OUTSTANDING_AMOUNT为920.00的5月31日记录 - 2022年6月返回
Cancelled状态,对应金额全0的注销记录
内容的提问来源于stack exchange,提问作者Petar Pan
相关产品推荐
相关产品推荐

