繁体   English   中英

在Join中转一个Mysql子查询

[英]Turn a Mysql Subquery in a Join

如何在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

使用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

这应该这样做:

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

这里的关键点是使用聚合来管理reklamationreklamation_status之间的基数。 在原始代码中,内联子查询使用ORDER BY reklamation_status.id DESC LIMIT 1返回reklamation_status中与当前reklamation对应的最高id 如果没有聚合,我们可能会在结果reklamation为每个reklamation获取多个记录(每个对应的reklamation_status )。

另一件事是考虑是JOIN的类型。 INNER JOIN会过滤掉的记录reklamation没有A S reklamation_status :与内联子查询的原始查询不那样做,所以我选择了LEFT JOIN 如果您可以保证每个reklamationreklamation中至少有一个子reklamation_status ,则可以安全地切换回INNER JOIN (可能更有效地执行)。


PS:

我读到子查询比JOIN慢。

这不是一个普遍的事实。 这取决于很多因素,如果没有看到确切的用例,就无法告知。

你读的是不正确的。 子查询可以更慢,更快或与联接相同。 我会把查询写成:

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 ,则需要某种聚合来获取最新状态。 这可能很昂贵。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM