与括号比较时有什么区别:WHERE(a,b)=(1,2)

时间:2016-07-06 07:03:51

标签: mysql sql sql-server oracle

我偶然发现了MySQL中的以下(有效)查询(当用=替换IN时,也适用于Oracle / MSSQL):

SELECT * from mytable WHERE (a, b)=(1,2)

相同
SELECT * from mytable WHERE a=1 and b=2

我认为MySQL docs中的定义在这里:

simple_expr:
  [...]
  | (expr [, expr] ...)
  [...]

这叫什么?使用它有什么优点和缺点吗?

2 个答案:

答案 0 :(得分:14)

使用IN()比较多个列与多个值组合时,可以非常方便:

 SELECT * FROM YourTable
 WHERE (col1,col2) IN((1,2),(2,3),(4,4)...)

而不是:

SELECT * FROM YourTable
WHERE (col1 = 1 and col2 = 2) OR
      (col1 = 2 and col2 = 3) OR
      (col1 = 4 and col2 = 4) OR
      ....

在查看了两个查询的执行计划之后,我可以说在Oracle中(使用基本相同的IN()),优化器以相同的方式评估两者并且都使用索引:

单独条件:

EXPLAIN PLAN FOR
SELECT * FROM dim_remedy_tickets_cache t
where t.tt_id = '1' and t.region_name = 'one';

6   |   0 | SELECT STATEMENT            |                              |     1 |   311 |    30   (0)| 00:00:01 |
7   |   1 |  TABLE ACCESS BY INDEX ROWID| DIM_REMEDY_TICKETS_CACHE     |     1 |   311 |    30   (0)| 00:00:01 |
8   |   2 |   INDEX RANGE SCAN          | DIM_REMEDY_TICKETS_HISTORYPK |     1 |       |    20   (0)| 00:00:01 |

综合条件:

EXPLAIN PLAN FOR
SELECT * FROM dim_remedy_tickets_cache t
where (t.tt_id,t.region_name) in  (('1','one'))

6   |   0 | SELECT STATEMENT            |                              |     1 |   311 |    30   (0)| 00:00:01 |
7   |   1 |  TABLE ACCESS BY INDEX ROWID| DIM_REMEDY_TICKETS_CACHE     |     1 |   311 |    30   (0)| 00:00:01 |
8   |   2 |   INDEX RANGE SCAN          | DIM_REMEDY_TICKETS_HISTORYPK |     1 |       |    20   (0)| 00:00:01 |

我假设所有RDBMS都会对此查询进行相同的评估。

  

行构造函数在其他上下文中是合法的。例如,以下两个语句在语义上是等效的(并且由优化器以相同的方式处理):

所以:

缺点 - 对某些人来说可能性较差,但基本上没有缺点。

优点 - 使用IN()更少代码和多列比较的组合:

答案 1 :(得分:0)

我认为这两个查询之间没有任何区别,优化器也可能会这样做。

您应该对两个查询运行执行计划,并亲自查看。

除此之外,更多的是偏好。双方都没有很多缺点和优点,所以选择你喜欢的那个。