3个表上的MySql查询未返回所有行

时间:2014-12-19 12:53:42

标签: mysql subquery

我有3个表:问题,选项,comments_to_options(opt_comments)。 我想编写一个查询,在每行中返回以下值,连接:

一个问题,所有选项,每个选项的所有评论。

我的查询是:

select 
concat('{', '"qid":"', q.q_id, '", "qt":"', q.q_title,
'", "op":[', group_concat('{"oi":"', o.op_id, '", "ot":"', o.opt_value, '", ', oc_list, '}' 
order by o.opt_upvotes desc), ']}') 
as r 
from questions q, options o,
(select o.op_id as ocid, concat('"oc":[', group_concat('{"oci":"', oc.opt_com_id, '", "occ":"', oc.opt_com_value, '"}' 
order by oc.opt_com_added_at), ']') 
as oc_list 
from options o, opt_comments oc 
where oc.opt_com_to=o.op_id 
group by o.op_id)
as r2
where o.op_id=r2.ocid 
and q.q_id=o.option_to 
group by q.q_id
order by q.q_added_at desc
limit 3;

但是上面的查询只给出那些至少有一条评论的选项。 我该怎么修改?

3 个答案:

答案 0 :(得分:1)

您正在使用旧的JOIN语法以及以逗号分隔的表和子查询列表。该语法是正确的,但会生成INNER JOIN个操作。此类连接会抑制与连接条件不匹配的行。

您需要采用LEFT JOIN语法。如果不重构整个查询,我会说你应该改变

 FROM a, 
      (select something from z) AS b
WHERE a.value=b.value 

 FROM a 
 LEFT JOIN (select something from z) AS b ON a.value=b.value

另外,请注意,您可能会遇到GROUP_CONCAT()中的字符串长度限制。阅读本文:

MySQL and GROUP_CONCAT() maximum length

答案 1 :(得分:1)

使用"左连接"。 例如:

create table opt (oid int,name varchar(100));
insert into opt values (1,'opt1');
insert into opt values (2,'opt2');
insert into opt values (3,'opt3');

create table optcom (oid int,com varchar(100));
insert into optcom values (1,'opt1_1');
insert into optcom values (1,'opt1_2');
insert into optcom values (3,'opt3_1');

使用"简单加入":

 select opt.*,optcom.* from opt join optcom on opt.oid=optcom.oid;

+------+------+------+--------+ | oid | name | oid | com | +------+------+------+--------+ | 1 | opt1 | 1 | opt1_1 | | 1 | opt1 | 1 | opt1_2 | | 3 | opt3 | 3 | opt3_1 | +------+------+------+--------+ 当"离开加入":

  select opt.*,optcom.* from opt left join optcom on opt.oid=optcom.oid;

+------+------+------+--------+ | oid | name | oid | com | +------+------+------+--------+ | 1 | opt1 | 1 | opt1_1 | | 1 | opt1 | 1 | opt1_2 | | 2 | opt2 | NULL | NULL | | 3 | opt3 | 3 | opt3_1 | +------+------+------+--------+

答案 2 :(得分:0)

为了跟进上述响应,修改了SQL以使用外连接: -

SELECT CONCAT('{', '"qid":"', q.q_id, '", "qt":"', q.q_title,'", "op":[', GROUP_CONCAT('{"oi":"', o.op_id, '", "ot":"', o.opt_value, '", ', oc_list, '}' ORDER BY o.opt_upvotes DESC), ']}') AS r 
FROM options o
LEFT OUTER JOIN questions q
ON q.q_id = o.option_to 
LEFT OUTER JOIN 
(
    SELECT o.op_id AS ocid, 
            CONCAT('"oc":[', GROUP_CONCAT('{"oci":"', oc.opt_com_id, '", "occ":"', oc.opt_com_value, '"}' ORDER BY oc.opt_com_added_at), ']') AS oc_list 
    FROM options o
    INNER JOIN opt_comments oc 
    ON oc.opt_com_to=o.op_id 
    GROUP BY o.op_id
) r2
ON o.op_id = r2.ocid 
GROUP BY q.q_id
ORDER BY q.q_added_at DESC
LIMIT 3;

看着这个我不确定加入子查询。这似乎带回了一个编码的字符串,但是除了实际的连接之外,实际上并没有使用这个子查询。

因此我不确定该子查询是否仅用于缩小返回的行(在这种情况下,使用INNER JOIN加入它是合适的 - 你也可以不带回编码的字符串),或者如果您发布了一直尝试调试的查询的缩减版本。