В чем разница при сравнении с круглыми скобками: WHERE (a, b) = (1,2)

18

Я наткнулся на следующий (действительный) запрос в MySQL (также работает в Oracle / MSSQL при замене = на IN ):

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

Это то же самое, что

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

Я думаю, что определение в Документах по MySQL находится здесь:

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

Что это называется? Есть ли какие-либо плюсы и минусы для его использования?

    
задан Manuel M 06.07.2016 в 09:03
источник
  • Плюсы. Меньше печатать. Cons. Не могу использовать индексы, которые, я думаю, - но я не уверен - легко проверить, хотя –  Strawberry 06.07.2016 в 09:06
  • в первом тесте EXPLAIN говорит мне, что одни и те же индексы используются в обоих запросах, кажется, что здесь нет разницы –  Manuel M 06.07.2016 в 09:10
  • Я думаю, что первый синтаксис менее ясен, если предложение where более сложное –  Gilad Green 06.07.2016 в 09:15
  • ANSI SQL Feature 641, «Конструкторы строк и таблиц». (Согласно developer.mimer.com/validator/parser200x/index.tml) –  jarlh 06.07.2016 в 09:23
  • Это очень полезно с подзапросами в форме, например, WHERE (a, b) IN (SELECT c, d FROM T) –  valex 06.07.2016 в 09:24
Показать остальные комментарии

2 ответа

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 |

Я предполагаю, что все РСУБД будут оценивать эти запросы одинаковыми.

  

Конструкторы строк являются законными в других контекстах. Например, следующие два оператора семантически эквивалентны (и обрабатываются оптимизатором таким же образом):

Итак:

Минусы - Может быть, менее читабельны для некоторых людей, но в основном нет недостатков.

Плюсы - Меньший код и комбинация сравнения нескольких столбцов с использованием IN() :

    
ответ дан sagi 06.07.2016 в 09:20
  • Таким образом, это тоже работает в Oracle (он не работает в SQL Server). –  Manuel M 06.07.2016 в 09:22
  • Очень удобно при выполнении IN, например. WHERE (a, b) IN (SELECT c1, c2 FROM .... –  jarlh 06.07.2016 в 09:24
  • @jarlh Вы правы, обновлены –  sagi 06.07.2016 в 09:27
  • @ManuelM Да, он работает с использованием IN (), я думаю, что он работает и в SQL-Server. –  sagi 06.07.2016 в 09:27
  • Это отличный и очень продуманный ответ! не так много здесь, ура! +1. –  Yossi 06.07.2016 в 15:43
Показать остальные комментарии
0

Я не думаю, что есть разница между этими двумя запросами, оптимизатор, вероятно, сделает то же самое.

Вы должны запустить план выполнения для обоих запросов и посмотреть для себя.

Кроме этого, это скорее предпочтение. Для обеих сторон не так много недостатков и плюсов, поэтому выберите тот, который вам больше нравится.

    
ответ дан Omri 06.07.2016 в 15:45