2014-12-19 116 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