2012-06-01 20 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 ;