多表关联场景下,如何查询不存在指定记录的数据?
查询不存在指定记录的用户解决方案
嗨,我来帮你搞定这个需求!你已经能查询到存在profile_field_id=1227且value_tinyint=0记录的用户,现在要反过来找不存在这类记录的用户,这里有几种靠谱的方法,结合你的表结构给你具体实现:
方法一:LEFT JOIN + IS NULL(直观易读)
这种方式通过左连接保留所有用户记录,再筛选出没有匹配目标条件的条目:
SELECT ua.*, u.* FROM user_accounts AS ua INNER JOIN users AS u ON u.id = ua.user_id LEFT JOIN account_profile_entries AS ape ON ape.user_account_id = ua.id LEFT JOIN profile_entries AS pe ON pe.id = ape.profile_entry_id AND pe.profile_field_id = 1227 AND pe.value_tinyint = 0 WHERE pe.id IS NULL;
逻辑说明:
- 把针对
profile_entries的过滤条件移到JOIN子句里,而不是WHERE LEFT JOIN会保留所有user_accounts和users的记录,无论是否有匹配的profile_entries- 最后通过
pe.id IS NULL筛选出完全没有符合目标条件记录的用户
方法二:NOT EXISTS(性能友好,逻辑清晰)
用NOT EXISTS子查询直接检查当前用户是否不存在目标记录,这种写法在多数数据库中性能表现很好(尤其是当表有合适索引时):
SELECT ua.*, u.* FROM user_accounts AS ua INNER JOIN users AS u ON u.id = ua.user_id WHERE NOT EXISTS ( SELECT 1 FROM account_profile_entries AS ape INNER JOIN profile_entries AS pe ON pe.id = ape.profile_entry_id WHERE ape.user_account_id = ua.id AND pe.profile_field_id = 1227 AND pe.value_tinyint = 0 );
逻辑说明:
- 子查询会验证当前用户是否存在符合条件的profile记录
NOT EXISTS会直接筛选出那些没有这类记录的用户,逻辑非常直观
方法三:NOT IN(注意避坑)
NOT IN也能实现需求,但要注意子查询不能返回NULL值,否则会导致结果为空:
SELECT ua.*, u.* FROM user_accounts AS ua INNER JOIN users AS u ON u.id = ua.user_id WHERE ua.id NOT IN ( SELECT ape.user_account_id FROM account_profile_entries AS ape INNER JOIN profile_entries AS pe ON pe.id = ape.profile_entry_id WHERE pe.profile_field_id = 1227 AND pe.value_tinyint = 0 AND ape.user_account_id IS NOT NULL -- 必须加这个避免NULL问题 );
逻辑说明:
- 子查询先找出所有存在目标记录的
user_account_id NOT IN筛选不在这个列表里的用户- 一定要加上
ape.user_account_id IS NOT NULL,否则如果子查询返回NULL,整个查询结果会是空的
小建议
优先选择NOT EXISTS或者LEFT JOIN + IS NULL,这两种写法在不同数据库中兼容性更好,性能也更稳定,逻辑上也更容易维护。
内容的提问来源于stack exchange,提问作者Amiga500
相关产品推荐
相关产品推荐

