[英]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
这里的关键点是使用聚合来管理reklamation
和reklamation_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
。 如果您可以保证每个reklamation
在reklamation
中至少有一个子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.