2014-12-19 118 views
1

我有3个表格:questions,options,comments_to_options(opt_comments)。 我想写一个查询,每行返回以下值,连接:对3个表格不返回所有行的MySql查询

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

我的查询是:

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; 

但上面的查询只给那些有他们至少一个评论的选项。 我应该如何修改?

回答

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

使用“左连接”。 实施例:

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 | +------+------+------+--------+

0

要在上述后续响应,SQL修改t o使用外连接: -

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加入它会很合适 - 并且您也可以不带回编码的字符串) ,或者如果您发布了您试图调试的查询的简化版本。

+0

不,我没有削减查询的任何部分,并且您的查询也只返回那些对它们有评论的选项。 –

+0

我已经修改了查询(左连接问题,而不是其他方式)。如果您的原始查询中没有任何内容,那么子查询就显得多余了。 – Kickstart