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

最高效SQL写法:查询同时含A、B事件且无C事件的用户ID

问题说明

现有user_events表存储用户行为事件,样例数据如下:

User_IDEvent_Type
user1A
user1B
user2C
user3A
user3B
user3D
user3E

需求为筛选出同时存在Event_Type为A、B的记录,且不存在Event_Type为C的记录的User_ID,上述样例的预期输出为user1、user3。已知表数据量约10万条,原方案为3次独立查询后取交集,需要更高效的实现方式。

最优实现方案

采用单次表扫描+分组条件聚合的写法,效率远高于多查询取交集的方案,核心逻辑是按用户ID分组后,直接在组内判断事件类型的满足情况,仅需扫描一次表即可完成所有计算。

简化写法(兼容MySQL、PostgreSQL等主流数据库)

SELECT User_ID
FROM user_events
GROUP BY User_ID
HAVING
  -- 校验存在A类事件
  SUM(Event_Type = 'A') > 0
  -- 校验存在B类事件
  AND SUM(Event_Type = 'B') > 0
  -- 校验不存在C类事件
  AND SUM(Event_Type = 'C') = 0;

全语法兼容写法(适配SQL Server等不支持条件直接写在SUM内的数据库)

SELECT User_ID
FROM user_events
GROUP BY User_ID
HAVING
  SUM(CASE WHEN Event_Type = 'A' THEN 1 ELSE 0 END) > 0
  AND SUM(CASE WHEN Event_Type = 'B' THEN 1 ELSE 0 END) > 0
  AND SUM(CASE WHEN Event_Type = 'C' THEN 1 ELSE 0 END) = 0;
效率优势说明
  • 原3次查询取交集的方案,需要至少3次扫描表/索引,还要额外做结果集的交集、差集运算,冗余IO和计算开销大
  • 上述聚合写法仅需1次表扫描,分组过程中即可完成所有条件判断,IO开销仅为原方案的1/3。如果为表创建(User_ID, Event_Type)的联合索引,还可以实现覆盖索引扫描,不需要回表查询数据,10万条数据场景下查询耗时可以控制在毫秒级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:51:15