如何根据user_id获取自身及关联用户的contracts记录?(含无关联场景)
解决方案
要实现你要的需求,核心是先确定需要查询的所有用户ID集合(目标用户+关联用户,无关联则只有目标用户),再用这个集合去匹配contracts表的user_id。以下是两种可行的SQL写法:
写法1:子查询+UNION获取用户集合
SELECT c.* FROM contracts c WHERE c.user_id IN ( -- 先获取目标用户自身 SELECT :target_user_id AS user_id UNION -- 再获取该用户主动关联的用户(如果存在) SELECT ul.linked_user_id FROM user_links ul WHERE ul.user_id = :target_user_id UNION -- 补充:如果目标用户是被关联的一方,也要把关联者包含进来 SELECT ul.user_id FROM user_links ul WHERE ul.linked_user_id = :target_user_id );
写法2:CTE(公共表表达式)更清晰
WITH relevant_users AS ( SELECT :target_user_id AS user_id UNION SELECT linked_user_id FROM user_links WHERE user_id = :target_user_id UNION SELECT user_id FROM user_links WHERE linked_user_id = :target_user_id ) SELECT c.* FROM contracts c JOIN relevant_users ru ON c.user_id = ru.user_id;
为什么你原来的LEFT JOIN写法失效?
你之前用LEFT JOIN user_links ul ON ul.user_id = contracts.user_id OR ul.linked_user_id = contracts.user_id的问题在于:
- 当
user_links中没有目标用户的关联记录时,LEFT JOIN会返回NULL,但你的查询逻辑没针对这种情况处理,导致无法筛选出目标用户自己的合同。 - 更关键的是,这种JOIN是把
contracts的每一行去匹配user_links,逻辑方向搞反了——应该先确定要查哪些用户,再去捞对应合同,而不是反过来。
补充说明
- 上面的写法考虑了双向关联:比如
user_links里有user_id=2, linked_user_id=1的记录时,查询user_id=1也能拿到user_id=2的合同。如果你的业务是单向关联(只存主动发起关联的记录),可以去掉第三个UNION的部分。 - 把
:target_user_id替换成你实际要查询的用户ID即可。
内容的提问来源于stack exchange,提问作者Stanislav Levchenko
相关产品推荐
相关产品推荐

