2012-06-01 48 views
3

使用使用@ N = @ N + 1的經典技巧來獲取某些有序列上的項目排名。現在在訂購之前,我需要通過內部連接它與其他表格過濾出基表中的一些值。所以查詢看起來是這樣的 - :在使用變量的索引中存在MySQL排名

SET @N=0; 
SELECT 
    @N := @N + 1 AS rank, 
    fa.id, 
    fa.val 
FROM 
    table1 AS fa 
    INNER JOIN table2 AS em 
     ON em.id = fa.id 
     AND em.type = "A" 
ORDER BY fa.val ; 

的問題是,如果我沒有在em.type索引,那麼一切工作正常,但如果我把一個索引上em.type,地獄和解開排列值而不是由val列排序的順序是這些行存儲在電子表格中。

這裏有樣品輸出 - :

沒有指數 - :

rank id   val 
1 05F8C7 55050.000000 
2 05HJDG 51404.733458 
3 05TK1Z 46972.008208 
4 05F2TR 46900.000000 
5 05F349 44433.412847 
6 06C2BT 43750.000000 
7 0012X3 42000.000000 
8 05MMPK 39430.399658 
9 05MLW5 39054.046383 
10 062D20 35550.000000 

與指數 - :

rank  id  val 
480  05F8C7 55050.000000 
629  05HJDG 51404.733458 
1603 05TK1Z 46972.008208 
466  05F2TR 46900.000000 
467  05F349 44433.412847 
3534 06C2BT 43750.000000 
15  0012X3 42000.000000 
1109 05MMPK 39430.399658 
1087 05MLW5 39054.046383 
2544 062D20 35550.000000 

我相信使用索引應該是完全透明的,輸出不應該受其影響。這是MySQL中的錯誤嗎?

+0

任何解決方案/評論? – bootkick

回答

0

這個「詭計」是一枚等待爆炸的炸彈。一個聰明的優化器會評估一個查詢,因爲它看起來合適,優化速度 - 這就是爲什麼它被稱爲優化器。我不認爲這個MySQL變量的使用被證明可以正常工作,但它工作正常。

正在工作,直到最近MariaDB優化器的改進。它可能會在主流MySQL中打破,因爲在5.6版本中尚未發佈優化器。

你可以做什麼(直到MySQL實現窗口函數)是使用自連接和分組。無論將來如何改進優化器,結果都是一致的。缺點是它可能不是非常有效:

SELECT 
    COUNT(*) AS rank, 
    fa.id, 
    fa.val 
FROM 
    table1 AS fa 
    INNER JOIN table2 AS em 
     ON em.id = fa.id 
     AND em.type = 'A' 

    INNER JOIN 

    table1 AS fa2 
    INNER JOIN table2 AS em2 
     ON em2.id = fa2.id 
     AND em2.type = 'A' 

     ON fa2.id <= fa.id 
          --- assuming that `id` is the Primary Key of the table 
GROUP BY fa.id 
ORDER BY fa.val ;