基于同一列多条件分组查询:筛选特定时段内仅发生WITHDRAW交易未发生DEPOSIT交易的账户
解决方法:找出仅发生取款交易的账户
针对你给出的交易表需求,我整理了几种高效的SQL查询方案,帮你筛选出指定时间段内**只有WITHDRAW(取款)、无任何DEPOSIT(存款)**的账户。
方法1:使用NOT EXISTS子查询
这种方法逻辑最直观:先锁定时间段内有取款交易的账户,再排除掉那些同期存在存款交易的账户。
SELECT DISTINCT acct_id FROM transactions WHERE date_of_tran BETWEEN '2021-Jun-20' AND '2021-Jun-21' AND trans_type = 'WITHDRAW' AND NOT EXISTS ( SELECT 1 FROM transactions t2 WHERE t2.acct_id = transactions.acct_id AND t2.date_of_tran BETWEEN '2021-Jun-20' AND '2021-Jun-21' AND t2.trans_type = 'DEPOSIT' );
逻辑拆解:
- 外层查询先筛选出目标时间段内有取款记录的账户;
NOT EXISTS子查询负责排查:如果该账户在同一时间段有过存款,就排除它;DISTINCT保证每个账户只返回一次,避免因多笔取款导致重复结果。
方法2:使用GROUP BY + HAVING子句
这种方法通过分组统计账户的交易类型特征,直接过滤出符合条件的账户,适合对聚合逻辑熟悉的场景。
写法A:通过唯一交易类型判断
SELECT acct_id FROM transactions WHERE date_of_tran BETWEEN '2021-Jun-20' AND '2021-Jun-21' GROUP BY acct_id HAVING COUNT(DISTINCT trans_type) = 1 AND MAX(trans_type) = 'WITHDRAW';
逻辑拆解:
- 先按账户分组,限定在目标时间段内;
COUNT(DISTINCT trans_type) = 1确保该账户只有一种交易类型;MAX(trans_type) = 'WITHDRAW'(用MIN也可以,因为只有一种类型)确认这个唯一类型是取款。
写法B:直接排除存款交易
SELECT acct_id FROM transactions WHERE date_of_tran BETWEEN '2021-Jun-20' AND '2021-Jun-21' GROUP BY acct_id HAVING SUM(CASE WHEN trans_type = 'DEPOSIT' THEN 1 ELSE 0 END) = 0;
逻辑拆解:
- 按账户分组后,用CASE语句统计每个账户的存款交易数量;
- 数量为0说明该账户在时间段内没有存款,结合WHERE子句的时间段过滤,剩下的就是只有取款的账户。
测试结果
针对你提供的示例数据,以上三种查询都会返回:
acct_id ------- B
完全符合预期——账户B在2021年6月20日至21日期间只有取款交易,无任何存款记录。
内容的提问来源于stack exchange,提问作者KMD
相关产品推荐
相关产品推荐

