【问题标题】:What is the difference when comparing with parentheses: WHERE (a, b)=(1,2)和括号比较有什么区别:WHERE (a, b)=(1,2)
【发布时间】:2016-11-08 03:39:21
【问题描述】:

我偶然发现了 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] ...)
  [...]

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

【问题讨论】:

  • 优点。少打字。缺点。我认为不能使用索引 - 但我不确定 - 虽然很容易验证
  • 在第一次测试中EXPLAIN 告诉我两个查询中使用了相同的索引,似乎这里没有区别
  • 如果 where 子句更复杂,我认为第一种语法不太清楚
  • ANSI SQL 功能 641,“行和表构造函数”。 (据developer.mimer.com/validator/parser200x/index.tml
  • 它对子查询非常有用,例如WHERE (a,b) IN (SELECT c,d FROM T)

标签: mysql sql sql-server oracle


【解决方案1】:

当需要使用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() 进行多列比较的组合:

【讨论】:

  • 所以这在 Oracle 中也有效(在 SQL Server 中无效)。
  • IN 时非常方便,例如WHERE (a, b) IN (SELECT c1,c2 FROM ....
  • @ManuelM 是的,它正在使用 IN() 工作,我认为它也适用于 SQL-Server。
  • 这是一个很棒且非常详尽的答案!这样的人不多,加油! +1。
  • 遗憾的是,如果右侧有空值WHERE (a,b,c) = (1,2,null)WHERE (a,b,c) IN (1,2,null) 也没有空值,则它不起作用(1,2,3/null 可能是查询参数)
猜你喜欢
  • 2012-07-03
  • 1970-01-01
  • 2018-06-27
  • 2013-06-25
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
相关资源
最近更新 更多