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

统计每年仅含取消会话的学员:哪条SQL查询正确?

统计每年仅拥有取消状态会话的学员数量:SQL查询对比分析

我有一个名为sessions的表,表结构及部分数据如下:

session_idsession_date_timementor_idmentee_idsession_statusmentor_domain_id
012021-02-12 00:00:003000920136canceled3
122021-02-12 00:00:003003220003finished6
232021-02-12 00:00:003002020026finished2
342021-02-12 00:00:003002520006finished6
452021-02-12 00:00:003001120006finished5
562021-02-13 00:00:003003620056finished5
672021-02-13 00:00:003001520130canceled6
782021-02-13 00:00:003000920073finished7
892021-02-13 00:00:003001020033finished5
9102021-02-13 00:00:003000420047finished5
10112021-02-14 00:00:003000420153finished6
11122021-02-15 00:00:003001520089canceled7
12132021-02-17 00:00:003004620162finished6
13142021-02-17 00:00:003000120012finished7
14152021-02-17 00:00:003002520126finished3
15162021-02-17 00:00:003000920118canceled7
16172021-02-17 00:00:003001720098finished7
17182021-02-18 00:00:003002520112canceled6
18192021-02-18 00:00:003000420072finished5
19202021-02-18 00:00:003000420110finished5
20212021-02-19 00:00:003001520160canceled4
21222021-02-20 00:00:003004420164finished4
22232021-02-20 00:00:003000220031finished2
10417104182022-09-15 00:00:003038421802finished3
10418104192022-09-15 00:00:003031821837finished4
10419104202022-09-15 00:00:003042421842finished5
10420104212022-09-15 00:00:003062321591canceled6

我需要统计每年仅拥有取消状态会话的学员数量,先后编写了两条SQL查询:

第一条SQL查询及结果

select  date_trunc('year', session_date_time) as year_dt,
        count(distinct mentee_id) as mentee_can_ses,
        round((count(distinct mentee_id)-lag(count(distinct mentee_id)) over())*1.0/lag(count(distinct mentee_id)) over(), 2) as mentee_dynamic     
from    sessions as s
where   mentee_id not in (select distinct mentee_id from sessions as s where session_status = 'finished')
group by    date_trunc('year', session_date_time)

查询结果:2021年11名学员,2022年20名学员。

第二条SQL查询及结果

with table1 as (
    select  mentee_id,
            date_trunc('year', session_date_time) as year_dt,
            count(session_id) filter(where session_status='finished') as ses_finished,
            count(session_id) filter(where session_status='canceled') as ses_canceled
    from        sessions as s
    group by    mentee_id, date_trunc('year', session_date_time)
    having  count(session_id) filter(where session_status='finished') = 0
)
select  year_dt,
        count(distinct mentee_id)
from        table1
group by    year_dt

(注:原查询中select distinct mentee_id多余,因为已经按mentee_id分组,每个分组对应唯一的mentee_id)

查询结果:2021年102名仅含取消会话的学员,2022年37名。


哪条查询正确?错误原因是什么?

第二条查询是正确的,第一条查询存在逻辑错误:

  • 第一条查询的核心错误:
    子查询select distinct mentee_id from sessions where session_status = 'finished'获取的是所有历史上有过完成会话的学员ID,不管这些完成会话发生在哪一年。外层的where mentee_id not in (...)会把这些学员全部过滤掉——哪怕某个学员在2021年只有取消会话,但2022年有完成会话,这个学员也会被排除在2021年的统计结果之外,完全不符合“按年度统计仅取消会话学员”的需求。

  • 第二条查询的逻辑合理性:

    1. 先按mentee_id和年度分组,精准统计每个学员在每一年的完成会话数和取消会话数;
    2. 通过having子句筛选出当年没有任何完成会话的学员(即该学员在当年的所有会话都是取消状态);
    3. 最后按年度汇总这些学员的数量,完全匹配需求。

另外,第二条查询中的select distinct mentee_id是多余的,因为已经按mentee_id分组,每个分组只会返回一个唯一的mentee_id,可以直接去掉distinct。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:09:50