如何编写SQL子查询找出无交易且无变量的用户?
解决思路与SQL方案
表关系梳理
- Users 与 AccountManager:一对多(单个AccountManager对应多个Users)
- AccountManager 与 Accounts:一对多(单个AccountManager对应多个Accounts)
- Accounts 与 Transactions:一对多(单个Account对应多个Transactions)
- Users 与 Variables:一对多(单个User对应多个Variables)
原查询问题分析
你写的内连接(JOIN)会直接过滤掉没有关联AccountManager、Accounts或Transactions的用户,完全不符合“筛选无Transactions用户”的需求;另外COUNT(t.Id)不能直接放在WHERE子句中,需要配合GROUP BY和HAVING使用。
可行解决方案
方案1:LEFT JOIN + GROUP BY + HAVING
通过左连接保留所有用户,再分组筛选无交易、无变量的记录:
SELECT u.* FROM Users u -- 若允许用户无AccountManager,将此处JOIN改为LEFT JOIN JOIN AccountManager am ON am.AccountManagerId = u.AccountManagerId LEFT JOIN Accounts a ON a.AccountManagerId = am.AccountManagerId LEFT JOIN Transactions t ON t.AccountId = a.Id LEFT JOIN Variables v ON v.UserId = u.UserId GROUP BY u.UserId, u.[Name], u.[其他需要查询的字段] -- 需包含所有SELECT的非聚合字段 HAVING COUNT(t.Id) = 0 AND COUNT(v.Id) = 0
提示:如果表存在重复关联记录,可改用
COUNT(DISTINCT t.Id)避免计数错误。
方案2:NOT EXISTS子查询(性能更优)
利用子查询直接排除存在交易或变量的用户,适合有索引的大表场景:
SELECT u.* FROM Users u -- 若允许用户无AccountManager,将此处JOIN改为LEFT JOIN JOIN AccountManager am ON am.AccountManagerId = u.AccountManagerId WHERE -- 排除该用户关联账户下有交易的情况 NOT EXISTS ( SELECT 1 FROM Accounts a JOIN Transactions t ON t.AccountId = a.Id WHERE a.AccountManagerId = am.AccountManagerId ) AND -- 排除该用户有Variables记录的情况 NOT EXISTS ( SELECT 1 FROM Variables v WHERE v.UserId = u.UserId )
额外说明
如果业务允许用户没有对应的AccountManager,只需将JOIN AccountManager替换为LEFT JOIN AccountManager,并根据需求决定是否添加am.AccountManagerId IS NULL的过滤条件。
内容的提问来源于stack exchange,提问作者jmath412
相关产品推荐
相关产品推荐

