3

@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 のバグですか?

4

1 に答える 1

0

この「トリック」は爆発を待っている爆弾でした。巧妙なオプティマイザーは、適切と思われるクエリを評価し、速度を最適化します。これが、オプティマイザーと呼ばれる理由です。このMySQL変数の使用は、期待どおりに機能することが文書化されているとは思いませんが、機能していました。

MariaDBオプティマイザーの最近の改善までは機能していました。(まだリリースされていない、まだベータ版の)5.6バージョンのオプティマイザにはいくつかの改善があるため、主流のMySQLでもおそらく壊れます。

(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 ;
于 2012-10-27T21:32:58.797 に答える