2014-02-25 143 views
0

我收到了一列表| id | postNumber |列。一個或多個條目屬於一個postNumber。我需要爲每個postNumber申請最新的條目。mysql - 替代IN()

SELECT `dienstbuch`.`id` , `dienstbuch`.`postNumber` 
FROM `dienstbuch` 
WHERE `dienstbuch`.`id` 
IN (
SELECT max(`dienstbuch`.`id`) 
FROM dienstbuch 
GROUP BY `dienstbuch`.`postNumber` 
) 
ORDER BY `id` DESC 
LIMIT 2000,10 

在包含多個條目的表上使用時,查詢需要很長時間。

我該如何改進?

+1

爲什麼按郵編分組?你在索引什麼 – exussum

+0

你想達到什麼目的?你需要每個postNumber最大ID? – Ashalynd

+0

你正確地將IN(子查詢)標識爲性能問題的原因。我相信dienstbuch表中的每一行都會執行子查詢,並且這對於大集合將會很昂貴。考慮使用內聯視圖和JOIN操作,或者針對特定查詢,完全避免子查詢。 (請參閱我的答案。)適當的索引也會提高性能,但真正的性能問題是(可能)重複執行子查詢。 – spencer7593

回答

3

這聽起來就好像你可以在一個直查詢

SELECT max(`dienstbuch`.`id`) maxId, postNumber 
FROM dienstbuch 
GROUP BY `dienstbuch`.`postNumber` 

但是,如果您檢索幾個字段,然後它需要一個子查詢

SELECT `dienstbuch`.`id` , `dienstbuch`.`postNumber`, dienstbuch.field1, dienstbuch.field2 
FROM `dienstbuch` 
JOIN 
(SELECT max(`dienstbuch`.`id`) id, postNumber 
FROM dienstbuch 
GROUP BY `dienstbuch`.`postNumber` 
) maxID 
on dienstbuch.id=maxID.id and dienstbuch.postNumber=maxID.postNumber 
ORDER BY dienstbuch.`id` DESC 
LIMIT 2000,10 
+2

+1。注意:如果'id'列是唯一的,那麼內聯視圖(在第二個查詢中)不需要返回postNumber。 (我假定它是唯一的)。如果postNumber可以爲NULL,那麼第二個查詢的結果與OP查詢略有不同,因爲它不會返回任何具有NULL postNumber的行,這是由於謂詞相等在ON子句中。 (等號比較器可以用無效比較器'<=>'替代)。 – spencer7593

2

爲了獲得更好的性能要求最高的ID,作爲替代IN (subquery)謂詞,可以使用JOIN添加到內聯視圖(又名派生表)。

例如:

SELECT d.id 
    , d.postNumber 
    FROM dienstbuch d 
    JOIN (SELECT MAX(e.id) AS max_id 
      FROM dienstbuch e 
      GROUP BY e.postNumber 
     ) f 
    ON f.max_id = d.id 
ORDER 
    BY d.id DESC 
LIMIT 2000,10 

這是因爲它的執行查詢的內聯視圖一次,而不是執行爲每個行子查詢,這是MySQL的是如何評價這IN (subquery)謂語應執行更好, 。

這是我們使用的正常模式,如果我們還需要結果集中的表中的其他列。對於您的特定查詢,您根本不需要子查詢。你可以得到同等的結果集與此查詢:

SELECT d.id 
    , d.postNumber 
    FROM dienstbuch d 
GROUP 
    BY d.postNumber 
ORDER 
    BY d.id DESC 
LIMIT 2000,10 

這很可能有更好的表現,因爲這會避免內嵌視圖,執行JOIN操作的開銷。

對於這兩個查詢,索引... ON dienstbuch (postNumber,id)都是提高查詢性能的最可能候選者。

+0

JOIN'實際上是內連接的同義詞還是什麼類型的連接? – Zulakis

+1

@Zulakis:是的,'JOIN'是'INNER JOIN'的同義詞。在MySQL中,'CROSS'和'INNER'關鍵字完全是可選的; 'JOIN','INNER JOIN'和'CROSS JOIN'在MySQL中都是同義詞。我們通常不使用INNER關鍵字,但是當我們故意省略ON子句時,我們通常包含'CROSS'關鍵字,主要是作爲閱讀我們聲明的人的文檔線索。 – spencer7593