在联接中打开一个Mysql子查询

时间:2019-04-06 21:16:48

标签: mysql sql

如何在JOIN中打开此子查询?

我了解到子查询比JOIN慢。

SELECT 
    reklamation.id, 
    reklamation.titel,
    ( 
        SELECT reklamation_status.status 
        FROM reklamation_status 
        WHERE reklamation_status.id_reklamation = reklamation.id 
        ORDER BY reklamation_status.id DESC 
        LIMIT 1 
    ) as status
FROM reklamation 
WHERE reklamation.aktiv=1

3 个答案:

答案 0 :(得分:0)

使用JOIN查询可以重写为:

SELECT reklamation.id, reklamation.titel, reklamation_status.status
FROM reklamation 
JOIN reklamation_status ON reklamation_status.id_reklamation = reklamation.id
WHERE reklamation.aktiv=1

答案 1 :(得分:0)

这应该做到:

SELECT r.id, r.titel, MAX(s.id) as status
FROM reklamation r
LEFT JOIN reklamation_status s ON s.id_reklamation = r.id
WHERE r.aktiv = 1   
GROUP BY r.id, r.titel

此处的重点是使用 aggregation 来管理reklamationreklamation_status之间的基数。在您的原始代码中,内联子查询使用ORDER BY reklamation_status.id DESC LIMIT 1返回id中与当前reklamation_status相对应的最高reklamation。如果不进行汇总,我们可能会在每个reklamation的结果集中获得多个记录(对于每个对应的reklamation_status则会得到一个记录)。

要考虑的另一件事是JOIN的类型。 INNER JOIN会过滤掉没有reklamation的{​​{1}}的记录:带有内联子查询的原始查询的行为就不一样了,所以我选择了reklamation_status。如果可以保证每个LEFT JOINreklamation中至少有一个孩子,则可以安全地切换回reklamation_status(这可能会更有效地执行操作)。


PS:

  

我了解到子查询比INNER JOIN慢。

这不是普遍真理。它取决于许多因素,只有在没有确切用例的情况下才能知道。

答案 2 :(得分:0)

您阅读的内容不正确。子查询可以更慢,更快或与联接相同。我将查询写为:

SELECT r.id, r.titel,
       (SELECT rs.status 
        FROM reklamation_status rs
        WHERE rs.id_reklamation = r.id 
        ORDER BY rs.id DESC 
        LIMIT 1 
       ) as status
FROM reklamation  r
WHERE r.aktiv = 1;

为了提高性能,您希望在reklamation_status(id_reklamation, id, status)上建立索引。

顺便说一句,在这种情况下,子查询可能是表达此查询的最快方法。如果尝试使用JOIN,则需要某种汇总以获取最新状态。那可能很贵。