我有这张桌子:
// QandA
+----+--------+----------------------------------------+------+---------+
| id | title | content | type | related |
+----+--------+----------------------------------------+------+---------+
| 1 | title1 | content of question1 | 0 | NULL |
| 2 | | content of first answer for question1 | 1 | 1 |
| 3 | title2 | content of question2 | 0 | NULL |
| 4 | title3 | content of question3 | 0 | NULL |
| 5 | | content of second answer for question1 | 1 | 1 |
| 6 | | content of first answer for question3 | 1 | 4 |
| 7 | title4 | content of question4 | 0 | NULL |
| 8 | | content of first answer for question2 | 1 | 3 |
+----+--------+----------------------------------------+------+---------+
-- type colum: it is 0 for questions and 1 for answers.
-- related column: it is NULL for questions and {the id of its own question} for answers.
我还有另外两张表:
// interface_tags
+---------+--------+
| post_id | tag_id |
+---------+--------+
| 1 | 1 |
| 1 | 5 |
| 3 | 4 |
| 4 | 1 |
| 4 | 2 |
| 4 | 5 |
| 7 | 2 |
+---------+--------+
// tags
+----+----------+
| id | tag_name |
+----+----------+
| 1 | PHP |
| 2 | SQL |
| 3 | MySQL |
| 4 | CSS |
| 5 | Java |
| 6 | HTML |
| 7 | JQuery |
+----+----------+
这是我的疑问:
SELECT id,
title,
content
(SELECT i_t.tag_name
FROM tags t
JOIN interface_tags i_t
ON t.id = i_t.tag_id
WHERE i_t.post_id = :id1) tag
FROM QandA
WHERE id = :id2 OR related = :id3
-- Note: :id1, :id2 and :id3 are identical
如您所见,我的查询同时选择了问题(id = :id2
)及其所有答案(related = :id3
)。有一个子查询可以获取问题的所有标签。但它将按行执行。因此,子查询将针对问题和答案执行。有很多浪费过程,因为答案没有标签。
我的问题是什么?如何避免执行该子查询以获得答案?我的意思是我只想针对这个问题执行该子查询。
编辑:这是预期的输出:
-- :id = 1
// QandA
+----+--------+----------------------------------------+------------+
| id | title | content | tag |
+----+--------+----------------------------------------+------------+
| 1 | title1 | content of question1 | PHP, JAVA |
| 2 | | content of first answer for question1 | |
| 5 | | content of second answer for question1 | |
+----+--------+----------------------------------------+------------+
答案 0 :(得分:2)
你需要CASE:
SELECT id,
title,
content,
CASE
WHEN type = 0 THEN -- get tags only when post type is QUESTION
(SELECT i_t.tag_name
FROM tags t
JOIN interface_tags i_t
ON t.id = i_t.tag_id
WHERE i_t.post_id = :id1)
ELSE -- else consider it an ANSWER and don't get tags
NULL
END tag
FROM QandA
WHERE id = :id2 OR related = :id3
答案 1 :(得分:1)
你试过这个吗?
SELECT q.id,
q.title,
q.content,
GROUP_CONCAT(i_t.tag_name)
FROM QandA q
LEFT JOIN interface_tags i_t
ON q.id = i_t.post_id
LEFT JOIN tags t
ON t.id = i_t.tag_id
WHERE
q.id = :id2 OR q.related = :id3
GROUP BY
q.id
这是您想要的可能解决方案。
答案 2 :(得分:1)
为什么不用UNION
执行两个单独的查询?
SELECT id, title, content,
(SELECT GROUP_CONCAT(t.tag_name)
FROM tags t
JOIN interface_tags i_t
ON t.id = i_t.tag_id
WHERE i_t.post_id = :id1) tag
FROM QandA WHERE id = :id2
UNION ALL
SELECT id, title, content, NULL
FROM QandA WHERE related = :id3
答案 3 :(得分:0)
您可以使用CASE
表达式,并添加1个参数,因此我们有:id1 ...:id4(全部相同)
SELECT
id,
title,
content
CASE WHEN id = :id1
THEN (SELECT i_t.tag_name
FROM tags t
JOIN interface_tags i_t
ON t.id = i_t.tag_id
WHERE i_t.post_id = :id2)
END tag
FROM
QandA
WHERE
id = :id3 OR related = :id4;