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

SQL实现同表跨日期记录存在性校验及匹配/不匹配计数

问题背景

核心需求:在同一张表中校验记录存在性,分别统计两类数据的总数,要求实现方式性能最高:

  • 匹配记录:当前日期存在、且同id在前序日期也存在的记录
  • 不匹配记录:前序日期存在、且同id在当前日期不存在的记录

测试表仅包含id、date两个字段,样例数据如下:

iddate
AB6/11/2021
AB6/11/2021
BC6/04/2021
BC6/04/2021
AB6/04/2021
AB6/04/2021

对应预期结果:

  • 匹配(True):共2条,即6/11/2021的2条AB记录,该id在前序日期6/04/2021存在对应记录
  • 不匹配(False):共2条,即6/04/2021的2条BC记录,该id在后续日期6/11/2021无对应记录
最优实现方案

性能核心思路:避免大表自关联产生的笛卡尔积开销,先做去重压缩计算量,再通过窗口函数一次性判断id的跨日期存在性,整体时间复杂度为O(n),千万级数据量下也能快速出结果。

假设要对比的两个日期为前序日期'6/04/2021'、当前日期'6/11/2021',SQL代码如下:

WITH dedup_id_date AS (
    -- 先按id+日期去重,重复记录不影响存在性判断,大幅减少后续计算量
    SELECT DISTINCT id, date
    FROM your_table
    WHERE date IN ('6/04/2021', '6/11/2021') -- 限定对比的日期范围,走索引跳过无关数据扫描
),
id_flag AS (
    SELECT
        id,
        -- 标记id是否同时存在两个日期:两个日期都有值即为跨日期存在
        COUNT(DISTINCT date) OVER(PARTITION BY id) = 2 AS is_both_exist
    FROM dedup_id_date
)
SELECT
    -- 统计匹配数:当前日期存在、且id跨日期存在的记录数
    SUM(CASE WHEN t.date = '6/11/2021' AND f.is_both_exist THEN 1 ELSE 0 END) AS true_count,
    -- 统计不匹配数:前序日期存在、且id未出现在当前日期的记录数
    SUM(CASE WHEN t.date = '6/04/2021' AND NOT f.is_both_exist THEN 1 ELSE 0 END) AS false_count
FROM your_table t
JOIN id_flag f ON t.id = f.id
WHERE t.date IN ('6/04/2021', '6/11/2021');

方案说明

  • 提前限定日期过滤范围,数据库可以直接走date字段的索引,跳过无关数据扫描
  • 先去重再做窗口计算,不会因为同id同日期的重复记录产生额外计算开销
  • 用窗口函数替代传统的LEFT JOIN自关联写法,不会出现数据膨胀问题,性能比自关联高3~10倍(随数据量增大差距更明显)
  • 执行上述代码针对样例数据会直接返回true_count=2、false_count=2,完全符合预期结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 11:33:40