递归SQL查询关联用户号码:UNION改UNION ALL触发无限循环求助
解决递归查询无限循环并获取所有关联用户号码的问题
要解决递归查询的无限循环问题,核心是跟踪已访问过的用户,避免重复处理同一用户导致的循环。以下是修正后的查询,既可以使用UNION ALL保证性能,也能正确终止递归:
WITH RECURSIVE user_connections AS ( -- 初始步骤:获取指定用户的所有号码,同时记录已访问的用户集合 SELECT un.id, un.user_id, un.number, ARRAY[un.user_id] AS visited_users FROM p2p_market.user_numbers un WHERE un.user_id = 3 -- 替换为你需要查询的目标user_id UNION ALL -- 递归步骤:通过号码关联找到未访问过的新用户,获取他们的所有号码 SELECT un.id, un.user_id, un.number, uc.visited_users || un.user_id FROM p2p_market.user_numbers un JOIN user_connections uc ON un.number = uc.number WHERE un.user_id <> ALL(uc.visited_users) -- 仅处理未被访问过的用户 ) -- 去重并排序,确保结果唯一且有序 SELECT DISTINCT id, user_id, number FROM user_connections ORDER BY user_id, id;
关键逻辑说明:
- 已访问用户跟踪:用
visited_users数组记录所有已经处理过的用户ID,递归时只处理不在这个数组中的用户,从根源上避免了循环(比如用户3和用户4通过123互相关联的情况)。 - UNION ALL的安全使用:因为每次递归只引入新用户的记录,不会重复处理旧数据,所以用
UNION ALL不会触发无限循环,同时比UNION性能更高。 - DISTINCT去重:同一个用户的号码可能通过不同关联路径被多次获取,
DISTINCT确保最终结果中每条记录唯一。
原查询的问题分析:
- 原查询没有跟踪已访问用户,仅靠
iun.user_id != fun.user_id无法阻止循环(比如用户3→4→3的关联会反复触发)。 UNION能正常运行是因为它会自动去重,当没有新记录产生时递归终止,但这种方式依赖去重逻辑,性能不如主动控制递归终止的方案。
内容的提问来源于stack exchange,提问作者V. Kuznetsov
相关产品推荐
相关产品推荐

