How can I turn this subquery in a JOIN
?
I read that subqueries are slower than JOIN
s.
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
Using JOIN
query can be rewritten to:
SELECT reklamation.id, reklamation.titel, reklamation_status.status
FROM reklamation
JOIN reklamation_status ON reklamation_status.id_reklamation = reklamation.id
WHERE reklamation.aktiv=1
This should do it:
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
The key point here is to use aggregation to manage the cardinality between reklamation
and reklamation_status
. In your original code, the inline subquery uses ORDER BY reklamation_status.id DESC LIMIT 1
to return the highest id
in reklamation_status
that corresponds to the current reklamation
. Without aggregation, we would probably get multiple records in the resultset for each reklamation
(one for each corresponding reklamation_status
).
Another thing is to consider is the type of the JOIN
. INNER JOIN
would filter out records of reklamation
s that do not have a reklamation_status
: the original query with the inline subquery does not behave like that, so I chose LEFT JOIN
. If you can guarantee that every reklamation
has at least one child in reklamation_status
, you can safely switch back to INNER JOIN
(which might perform more efficiently).
PS:
I read that subqueries are slower than
JOIN
s.
This is not a universal truth. It depends on many factors and cannot be told without seeing your exact use case.
What you read is incorrect. Subqueries can be slower, faster, or the same as joins. I would write the query as:
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;
For performance, you want an index on reklamation_status(id_reklamation, id, status)
.
By the way, this is a case where the subquery is probably the fastest method for expressing this query. If you attempt a JOIN
, then you need some sort of aggregation to get the most recent status. That can be expensive.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.