IN子句

时间:2017-06-22 17:46:07

标签: mysql sql where-in

我有一个数据库,其中有四列对应于起始位置和结束位置的地理坐标x,y。列是:

  • X0
  • Y0
  • X1
  • Y1

我有这四列的索引,序列为x0,y0,x1,y1。

我有一百个地理对的组合列表。我如何有效地查询这些数据?

我想按this SO answer的建议做这样的事情,但它只适用于Oracle数据库,而不适用于MySQL:

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

我原以为可以用索引做点什么?什么是最好的方法(即:最快的查询)?谢谢你的帮助!

注意:

  • 我无法更改数据库的架构
  • 我有大约100' 000' 000行

修改 代码原样实际上正在工作,但它非常慢并且没有利用索引(因为我们有一个旧版本的MySQL v5.6.27)。

5 个答案:

答案 0 :(得分:12)

为了有效地使用索引,您可以重写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 )
)

答案 1 :(得分:7)

MySQL允许像你所示的行构造函数比较,但优化器在MySQL 5.7之前不知道如何使用索引来帮助提高性能。

答案 2 :(得分:5)

我不明白你的观点。以下查询是有效的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子句中的相等比较将利用索引。

答案 3 :(得分:2)

您可以将concatenate四个值转换为字符串,然后按以下方式进行检查:

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

答案 4 :(得分:0)

您正在做的是在我的机器上的mysql版本中提供正确的结果。我正在使用v5.5.55。也许你正在使用较旧的。请检查一下。

如果您仍想在自己的版本中解决此问题或上述解决方案无效,则只阅读下一个解决方案。

我仍然不清楚这里所有列的数据类型和范围。所以我假设数据类型是整数,范围介于0到9之间。如果是这种情况,您可以轻松地执行此操作,如下所示。

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