web-dev-qa-db-ja.com

IN句のMySQL複数列

開始位置と終了位置の地理座標x、yに対応する4つの列を持つデータベースがあります。列は次のとおりです。

  • x0
  • y0
  • x1
  • y1

シーケンスx0、y0、x1、y1のこれら4つの列のインデックスがあります。

地理的ペアの約100の組み合わせのリストがあります。このデータを効率的に照会するにはどうすればよいですか?

this SO answer で提案されているように、次のようなことをしたいと思いますが、MySQLではなくOracleデータベースに対してのみ機能します。

SELECT * FROM my_table WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1));

私はインデックスで何かをすることができるかもしれないと思っていましたか?最善のアプローチは何ですか(つまり、最速のクエリ)。ご協力いただきありがとうございます!

ノート:

  • データベースのスキーマを変更できません
  • 約10万行あります

EDIT:実際のコードは実際に動作していましたが、非常に遅く、インデックスを利用しませんでした(以前のバージョンのMySQL v5.6.27)。

11
nbeuchat

インデックスを効果的に使用するには、IN述語を書き換えます。

(x0, y0, x1, y1) IN ((4, 3, 5, 6),(9, 3, 2, 1))

このような:

(  ( x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6 ) 
OR ( x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1 )
)
12
spencer7593

MySQLは、示されているように行コンストラクターの比較を許可しますが、オプティマイザーはMySQL 5.7までパフォーマンスを向上させるためにインデックスを使用する方法を知りませんでした。

7
Bill Karwin

私はあなたの主張を理解していません。次のクエリは有効なMySQL構文です。

SELECT *
FROM my_table
WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1));

MySQLは、あなたが説明した複合インデックスを使用することを期待しています。しかし、もしそれができなければ:

SELECT *
FROM my_table
WHERE x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6
UNION ALL
. . .
SELECT *
FROM my_table
WHERE x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1

WHERE句の等値比較willはインデックスを利用します。

6
Gordon Linoff

連結 4つの値を文字列に変換し、次のようにチェックできます。

SELECT * 
FROM my_table 
WHERE CONCAT_WS(',', x0, y0, x1, y1) IN ('4,3,5,6', ..., '9,3,2,1');
2
sorayadragon

あなたのやり方は、私のマシンのmysqlバージョンで正しい結果を出すことです。使っています v5.5.55。たぶんあなたは古いものを使用しています。確認してください。

自分のバージョンでこの問題を解決したい場合、または上記の解決策が機能しない場合は、次の解決策のみをお読みください。

ここでは、すべての列のデータ型と範囲についてはまだ明確ではありません。したがって、データ型は整数であり、範囲は0〜9であると想定しています。その場合は、以下に示すように簡単に行うことができます。

select * from s1 where x0+10*x1+100*y1+1000*y2 in (4356,..., 9321);
0
Chandan Purbia