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

如何用单条SQL查询关联问题表与答案表并解决子查询多列报错?

问题根源

你遇到的「operand should contain 1 column(s)」错误,核心原因是:你在SELECT列表里写的子查询试图返回多列(A.answer_body, A.answer_id等),但标量子查询(作为SELECT字段的子查询)只能返回单个值,数据库自然会报错。

解决方案:两种实用实现思路

针对「获取单个问题的所有信息+关联的所有答案」这个需求,分享两种常用的实现方式:

方案1:用LEFT JOIN + JSON聚合打包答案(推荐)

如果你的MySQL版本是8.0+,可以用JSON_AGG直接把多条答案转换成JSON数组;如果是5.7+,可以用GROUP_CONCAT结合JSON_OBJECT拼接。同时优化投票数计算,用一次聚合查询代替多次子查询,提升效率。

示例SQL(MySQL 8.0+):

SET @question_id = 56;

SELECT
  Q.*,
  CONCAT(m.firstname, ' ', m.lastname) AS author_name,
  m.username AS u_name,
  -- 将关联答案打包成JSON数组
  JSON_AGG(
    JSON_OBJECT(
      'answerid', A.answer_id,
      'body', A.answer_body,
      'askid', A.ask_id,
      'answered_by_user_id', A.user_id
    )
  ) AS answers,
  -- 统计反对票
  COUNT(CASE WHEN v.vote_type = 0 THEN v.vote_id END) AS votes_down,
  -- 统计赞成票
  COUNT(CASE WHEN v.vote_type = 1 THEN v.vote_id END) AS votes_up
FROM QUESTIONS_TB Q
LEFT JOIN ANSWERS_TB A ON Q.question_id = A.ask_id
LEFT JOIN MAIN_TABLE m ON Q.user_id = m.user_id
LEFT JOIN VOTES_TB v ON Q.question_id = v.ask_id
WHERE Q.question_id = @question_id
GROUP BY Q.question_id, m.firstname, m.lastname, m.username;

如果是MySQL 5.7,替换JSON_AGG为GROUP_CONCAT:

SET @question_id = 56;

SELECT
  Q.*,
  CONCAT(m.firstname, ' ', m.lastname) AS author_name,
  m.username AS u_name,
  GROUP_CONCAT(
    JSON_OBJECT(
      'answerid', A.answer_id,
      'body', A.answer_body,
      'askid', A.ask_id,
      'answered_by_user_id', A.user_id
    ) SEPARATOR ','
  ) AS answers,
  COUNT(CASE WHEN v.vote_type = 0 THEN v.vote_id END) AS votes_down,
  COUNT(CASE WHEN v.vote_type = 1 THEN v.vote_id END) AS votes_up
FROM QUESTIONS_TB Q
LEFT JOIN ANSWERS_TB A ON Q.question_id = A.ask_id
LEFT JOIN MAIN_TABLE m ON Q.user_id = m.user_id
LEFT JOIN VOTES_TB v ON Q.question_id = v.ask_id
WHERE Q.question_id = @question_id
GROUP BY Q.question_id, m.firstname, m.lastname, m.username;

拿到结果后,在应用层(比如PHP)用json_decode把answers字段转换成数组,就能轻松获取所有答案。

方案2:直接LEFT JOIN返回多行,应用层合并数据

这种方式更直观,不需要聚合函数,数据库会返回多行结果(每个答案对应一行,问题信息重复),你只需要在应用层把同一个问题的答案整理到数组里即可。

示例SQL:

SET @question_id = 56;

SELECT
  Q.*,
  CONCAT(m.firstname, ' ', m.lastname) AS author_name,
  m.username AS u_name,
  A.answer_id AS answerid,
  A.answer_body AS body,
  A.ask_id AS askid,
  A.user_id AS answered_by_user_id,
  (SELECT COUNT(v.vote_id) FROM VOTES_TB v WHERE v.ask_id = Q.question_id AND v.vote_type = 0) AS votes_down,
  (SELECT COUNT(v.vote_id) FROM VOTES_TB v WHERE v.ask_id = Q.question_id AND v.vote_type = 1) AS votes_up
FROM QUESTIONS_TB Q
LEFT JOIN ANSWERS_TB A ON Q.question_id = A.ask_id
LEFT JOIN MAIN_TABLE m ON Q.user_id = m.user_id
WHERE Q.question_id = @question_id;

比如在PHP里,你可以先提取第一条记录的问题信息,再遍历所有结果把答案收集到一个数组中,最终得到「问题+所有答案」的完整结构。

重要提醒:避免SQL注入

你原来的代码直接把$question_id拼入SQL,存在严重的SQL注入风险。建议改用预处理语句,比如PHP的PDO实现:

$question_id = 56;
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("
  -- 填入上面的SQL语句,将WHERE条件改为 Q.question_id = ?
");
$stmt->execute([$question_id]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:33:46