简体   繁体   English

在Join中转一个Mysql子查询

[英]Turn a Mysql Subquery in a Join

How can I turn this subquery in a JOIN ? 如何在JOIN转换此子查询?

I read that subqueries are slower than JOIN s. 我读到子查询比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

Using JOIN query can be rewritten to: 使用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

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 . 这里的关键点是使用聚合来管理reklamationreklamation_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 . 在原始代码中,内联子查询使用ORDER BY reklamation_status.id DESC LIMIT 1返回reklamation_status中与当前reklamation对应的最高id Without aggregation, we would probably get multiple records in the resultset for each reklamation (one for each corresponding reklamation_status ). 如果没有聚合,我们可能会在结果reklamation为每个reklamation获取多个记录(每个对应的reklamation_status )。

Another thing is to consider is the type of the JOIN . 另一件事是考虑是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 . INNER JOIN会过滤掉的记录reklamation没有A S reklamation_status :与内联子查询的原始查询不那样做,所以我选择了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). 如果您可以保证每个reklamationreklamation中至少有一个子reklamation_status ,则可以安全地切换回INNER JOIN (可能更有效地执行)。


PS: PS:

I read that subqueries are slower than JOIN s. 我读到子查询比JOIN慢。

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) . 为了提高性能,您需要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. 如果您尝试JOIN ,则需要某种聚合来获取最新状态。 That can be expensive. 这可能很昂贵。

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

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