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

SQL查询:获取客户连续活跃的最早起始日期

需求说明

现有包含CLIENT_ID、START_CONTRACT_DATE、END_CONTRACT_DATE的数据集,需要查询每个客户无中断连续活跃周期的最早起始日期——这里的连续指后续合同的起始日期与前一份合同的结束日期完全衔接(无间隔),且该周期需是当前仍在延续(或覆盖到最晚活跃状态)的连续链。

示例1

CLIENT_IDCONTRACT_IDSTART_CONTRACT_DATEEND_CONTRACT_DATE
2501/01/201205/04/2015
2605/04/201513/06/2017
2713/06/201722/05/2019
2822/05/201931/12/9999

结果:01/01/2012
所有合同完全衔接,从最早日期一直延续到活跃至今

示例2

CLIENT_IDCONTRACT_IDSTART_CONTRACT_DATEEND_CONTRACT_DATE
1101/01/201205/04/2015
1202/09/201514/01/2017
1313/06/201431/12/9999
1425/03/201906/08/2020

结果:13/06/2014
这份合同的结束日期为活跃至今,且无中断,是当前延续的连续周期起点

示例3

CLIENT_IDCONTRACT_IDSTART_CONTRACT_DATEEND_CONTRACT_DATE
3501/01/201205/04/2015
3605/04/201513/06/2017
3713/06/201722/05/2018
3822/05/201931/12/9999

结果:22/05/2019
前三个合同链在2018年结束后,2019年的合同与之前有间隔,当前延续的周期从2019年开始

解决方案

SAS Proc SQL 实现

核心思路是反向追溯:从最晚结束的合同(即END_CONTRACT_DATE = '31/12/9999',需先转换为SAS日期值)开始,不断向前找衔接的合同,直到找不到上一份衔接合同为止,最终取链中最小的起始日期。

代码如下:

proc sql;
    create table client_continuous_start as
    with recursive contract_chain as (
        -- 初始步骤:取每个客户当前活跃的合同(结束日期为9999-12-31)
        select 
            client_id,
            start_contract_date,
            end_contract_date
        from your_table_name
        where end_contract_date = input('31/12/9999', ddmmyy10.)
        
        union all
        
        -- 递归步骤:向前找与当前链中最早合同衔接的上一份合同
        select 
            c.client_id,
            c.start_contract_date,
            c.end_contract_date
        from your_table_name c
        inner join contract_chain cc
            on c.client_id = cc.client_id
            and c.end_contract_date = cc.start_contract_date
    )
    select 
        client_id,
        min(start_contract_date) as earliest_continuous_start format=ddmmyy10.
    from contract_chain
    group by client_id;
quit;

说明:

  • 替换your_table_name为实际数据集名称;
  • input('31/12/9999', ddmmyy10.)将字符型结束日期转为SAS日期值,确保日期比较准确;
  • 递归会持续向上匹配衔接合同,直到无匹配项,最终的最小起始日期即为目标值。

标准SQL 实现(适用于其他支持递归的数据库)

如果使用MySQL 8.0+、PostgreSQL、SQL Server等数据库,思路一致,仅需调整日期格式处理:

WITH RECURSIVE contract_chain AS (
    -- 初始:取活跃至今的合同
    SELECT 
        client_id,
        start_contract_date,
        end_contract_date
    FROM your_table_name
    WHERE end_contract_date = '9999-12-31'
    
    UNION ALL
    
    -- 递归向前找衔接合同
    SELECT 
        c.client_id,
        c.start_contract_date,
        c.end_contract_date
    FROM your_table_name c
    JOIN contract_chain cc
        ON c.client_id = cc.client_id
        AND c.end_contract_date = cc.start_contract_date
)
SELECT 
    client_id,
    MIN(start_contract_date) AS earliest_continuous_start
FROM contract_chain
GROUP BY client_id;

内容的提问来源于stack exchange,提问作者André Cordeiro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:27:18