簡體   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