使用@ N = @ N + 1的经典技巧来获取某些有序列上的项目等级。在订购之前,我需要通过内部连接它与其他表来过滤掉基表中的一些值。所以查询看起来像这样 - :
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列排序按顺序将行存储在em表中。
这里是示例输出 - :
没有索引 - :
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 :(得分: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 ;