Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何避免对某些行执行子查询?_Mysql_Sql - Fatal编程技术网

Mysql 如何避免对某些行执行子查询?

Mysql 如何避免对某些行执行子查询?,mysql,sql,Mysql,Sql,我有这张桌子: // QandA +----+--------+----------------------------------------+------+---------+ | id | title | content | type | related | +----+--------+----------------------------------------+------+---------+ | 1 | titl

我有这张桌子:

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

您可以使用
CASE
表达式,然后再添加一个参数,这样我们就有了:id1…:id4(全部相同)

你需要一个案例:

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
你试过这个吗

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    

这是您想要的可能解决方案。

为什么不使用
联合执行两个单独的查询呢

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


也许使用
解释
将有助于实际发生的事情,而不是你认为正在发生的事情。请不要告诉我“你必须使用两个单独的表格来回答问题和答案”。与其把表格扔给我们,如果您描述了业务问题,并向我们展示了预期的输出,那会很有帮助。@TimBiegeleisen我添加了预期的结果…@stack-因为两个单独的查询将更易于编写和读取。此外,您将在一个数组中设置标记。对于一个查询,您首先需要从问题中提取标记并解析字符串。我认为在该子查询的
WHERE
子句上使用
type=0
比使用
CASE
要好得多。我说得对吗?我认为对子查询的
WHERE
子句使用
type=0
比使用
CASE
要好得多。我说得对吗?写了这么长的评论后,我意识到你在问别的问题。好的,我的答案仍然是否定的,因为如果你把条件放在子查询的
WHERE
中,它仍然会命中
标记
表,并过滤所有行以获得明显的
false
条件<代码>案例<代码>语句将阻止在表中进行无用的搜索。您刚才说的“表中无用的搜索”是什么意思?考虑它像<代码>如果是“< /COD>”,“代码>如果type=0 < /COD>搜索表并获得标签<代码> EX/<代码>返回NULL。现在假设我们删除这个条件,并说让我们搜索帖子标签,无论
类型是什么,对于
问题
,查询将返回一些结果集,但是对于
答案
将没有结果。那么,当您知道查询将不返回任何结果时,为什么要执行查询呢?这就是为什么我称它为无用的搜索。子选择可以返回多行。您需要在子选择中使用
SELECT GROUP\u CONCAT(t.tag\u name)
。在您的查询中,这两个
左连接将对所有行执行。问题和答案。您可以对第一个左联接使用附加条件:
q.type=0
Yes它将更有用。因此,您可以在连接时使用更多条件。这可能是最快的解决方案。但是您需要在子选择中使用
SELECT GROUP\u CONCAT(t.tag\u name)
。@不,这不是最快的解决方案。。这是最干净的。实际上,我已经创建了一个基准并对其进行了测试
其中id=:id2或相关=:id3
使用比
union
更快的索引合并。然后使用
union ALL
。此外,还应切换(外部)WHERE条件。您正在为每个答案执行子选择。@PaulSpiegel同意,其中
条件是错误的,并且
UNION ALL
将更快。我假设原始子查询是正确的,您能用所需的
组\u CONCAT
编辑它吗?还修复了
标记名的缺少的
和错误的表别名。
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