我偶然发现了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] ...)
[...]
这叫什么?使用它有什么优点和缺点吗?
答案 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)
我认为这两个查询之间没有任何区别,优化器也可能会这样做。
您应该对两个查询运行执行计划,并亲自查看。
除此之外,更多的是偏好。双方都没有很多缺点和优点,所以选择你喜欢的那个。