You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JOIN所用主键列存在多值时关联两张SQL表得到预期结果

问题原因

你现有写法的问题是substring(user_id::VARCHAR FROM '[0-9]+')只会提取整个user_id字段中第一个匹配的数字串,遇到逗号分隔的多用户标识时,只能拿到第一个用户的ID,自然只能匹配到第一个用户名。

解决思路

  1. 先将VISITS表中逗号分隔的用户标识拆分为单行单个用户标识
  2. 对拆分后的单个用户标识提取数字部分,关联USERS表拿到用户名
  3. 按visited_page分组,将同页面的用户名用分号拼接输出

不同数据库实现示例

PostgreSQL 写法

SELECT 
  v.visited_page,
  string_agg(u.user_name, ';' ORDER BY u.user_id) AS user_name
FROM (
  -- 拆分逗号分隔的user_id为单行
  SELECT 
    visited_page,
    unnest(string_to_array(user_id, ',')) AS single_user_id
  FROM VISITS
) v
JOIN USERS u 
  ON substring(v.single_user_id FROM '[0-9]+')::INT = u.user_id
GROUP BY v.visited_page
ORDER BY v.visited_page;

MySQL 8.0+ 写法

WITH RECURSIVE split_ids AS (
  SELECT 
    visited_page,
    user_id AS remaining_ids,
    NULL AS single_user_id
  FROM VISITS
  UNION ALL
  SELECT 
    visited_page,
    IF(INSTR(remaining_ids, ',') = 0, '', SUBSTRING(remaining_ids, INSTR(remaining_ids, ',') + 1)),
    SUBSTRING_INDEX(remaining_ids, ',', 1)
  FROM split_ids
  WHERE remaining_ids != ''
)
SELECT 
  s.visited_page,
  GROUP_CONCAT(u.user_name ORDER BY u.user_id SEPARATOR ';') AS user_name
FROM split_ids s
JOIN USERS u 
  ON CAST(REPLACE(s.single_user_id, 'user_', '') AS UNSIGNED) = u.user_id
WHERE s.single_user_id IS NOT NULL
GROUP BY s.visited_page
ORDER BY s.visited_page;

Hive/Spark SQL 写法

SELECT 
  v.visited_page,
  concat_ws(';', collect_list(u.user_name)) AS user_name
FROM VISITS v
LATERAL VIEW explode(split(v.user_id, ',')) t AS single_user_id
JOIN USERS u 
  ON cast(regexp_extract(t.single_user_id, '[0-9]+', 0) AS INT) = u.user_id
GROUP BY v.visited_page
ORDER BY v.visited_page;

内容的提问来源于stack exchange,提问作者sqlbeginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 23:45:02