2016-06-24 12 views
1

カーソルベースのページ番号を使用してクエリを実行するテーブルがありますが、複数の列を適用する必要があります。複数の列を持つMySQLカーソルベースのページ番号

はのは、2つのカラムを使用しての簡単な例を見てみましょう - 私はこのような最初のページの取得:

SELECT column_1, column_2 
FROM table_name 
ORDER BY column_1, column_2 
LIMIT 10 

私は結果を取得した後、私は最後の行に基づいて、次のページを取得することができます。最後の行がcolumn_1 = 5, column_2 = 8であったとします。私はこのようなことをしたい:

SELECT column_1, column_2 
FROM table_name 
WHERE column_1 > 5 AND column_2 > 8 
ORDER BY column_1, column_2 
LIMIT 10 

これは明らかに間違っている。それは私がこの問題を回避するために、このような何かを行うことができます(なぜならcolumn_2上のフィルタの)

を(なぜならcolumn_1上のフィルタの)column_1 = 5, column_2 = 9を持っている行またはcolumn_1 = 6, column_2 = 6を持つ行を除外します:

SELECT column_1, column_2 
FROM table_name 
WHERE column_1 > 5 
OR (column_1 = 5 AND column_2 > 8) 
ORDER BY column_1, column_2 
LIMIT 10 

しかし、これは非常に面倒で2つの以上の列の発生しやすいエラーになり...また

は、私のユースケースは、複数の種類(INT UNSIGNEDBINARY)の列が含まれていますが、すべてが同等である

ご意見はありますか?

ありがとうございます!

答えて

2

場合は(残念ながらという名前の)列Column_1がユニークである、あなただけ行うことができます:

WHERE Column_1 > :last_retrieved_value 

質問から、Column_1が一意でないことが表示されますが、(Column_1,Column_2)タプルはユニークです。から保存された「次のページ」のクエリのための一般的な形式は、これらの2つのカラムの最後に取得した値を使用して、これら2列の順序は、だろう

...

(Column1,Column2) > (:lrv_col1,:lrv_col2) 

(LRV =値

WHERE t.Column_1 > :lrv_col1 
    OR (t.Column_1 = :lrv_col1 AND t.Column_2 > :lrv_col2) 

かを、私たちは、私が好むれ、このようにそれを書くことができます:MySQLの中にその状態を書き込むには、前のクエリによって取得した最後の行)

は、我々はあなたが示しているようにそれを行うことができますMySQLはOR条件によって混乱や間違ったインデックスを使用するためのチャンスをはるかに少ないがありますので...

WHERE t.Column_1 >= :lrv_col1 
     AND (t.Column_1 > :lrv_col1 OR t.Column_2 > :lrv_col2) 
ORDER BY t.Column_1, t.Column_2 
LIMIT n 

は、状態を確認するために、列にそれを拡張するには...

(c1,c2,c3) > (:lrv1,:lrv2,:lrv3) 

我々はちょうど2つの列のようにそれを壊し、最初c1を扱う、ちょうど2つの列の場合のようにそれを扱う:

WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (...)) 
ORDER BY c1, c2, c3 
LIMIT n 

そして今、そのプレースホルダが...(ちょうど持っていただろうしを確認する必要があるので、同じパターンを使用してそれを拡張することができます:

WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (c2 >= :lrv2 
          AND (c2 > :lrv2 OR c3 > :lrv3) 
          ) 
      ) 
ORDER BY c1,c2,c3 
LIMIT n 

拡大が少し乱雑に見えることに同意します。しかし、それは非常に規則的なパターンに従います。同様に、我々は

(c1,c2,c3,c4) > (:lrv1,:lrv2,:lrv3,:lrv4) 

は、私達はちょうど私たちは3つの列を持っているものを取る... 列の状態を表現することができ、我々は(c3 >= :lrv3 AND (c3 > :lrv3 OR c4 > :lrv4))

に置き換えることを c3 > :lrv3を拡張する必要があります援助将来のリーダーとして
WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (c2 >= :lrv2 
          AND (c2 > :lrv2 OR (c3 >= :lrv3 
                AND (c3 > :lrv3 OR c4 > :lrv4) 
               ) 
           ) 
          ) 
      ) 
ORDER BY c1,c2,c3,c4 
LIMIT n 

、私はこのブロックをコメントする、と意図を示すだろう...

-- (c1,c2,c3,c4) > (lr1,lr2,lr3,lr4) 

そして、もしMySQLがそういう比較を表現することができればいいと思います。残念ながら、MySQLを理解できるようにする必要があります。

+0

詳細な回答ありがとうございます! 私はシンプルな "タプル"比較を試してみましたが、それは機能しました(MySQL 5.6)。いくつかの 'EXPLAIN'クエリを実行して、拡張バージョンよりも優れているかどうかを確認しようとしています... – amitayh

+0

Ha!私はMySQLがそのタプル比較構文をサポートしていることを知らなかった!それは展開よりもはるかに簡単だろう。 '(c1、c2、c3)>(r1、r2、r3)'。はい、EXPLAINプランをチェックしてください... MySQLがインデックス範囲スキャン操作を使用し、c1、c2、c3を先頭の列として使用したいと考えています。 – spencer7593

関連する問題