我有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;
但是上面的查询只给出那些至少有一条评论的选项。 我该怎么修改?
答案 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()
中的字符串长度限制。阅读本文:
答案 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加入它是合适的 - 你也可以不带回编码的字符串),或者如果您发布了一直尝试调试的查询的缩减版本。