Разница между EXISTS и JOIN, чтобы проверить наличие записей - PullRequest
0 голосов
/ 12 декабря 2018

Рассматривая следующий пример:

SELECT *
FROM customers
WHERE EXISTS
    (SELECT *
     FROM order_details
     WHERE customers.customer_id = order_details.customer_id)
;

Какие различия существуют между эквивалентным запросом на основе inner join между двумя таблицами, которые получают один и тот же набор результатов?

I'mобеспокоен техническим аспектом / аспектом производительности, а не удобочитаемостью / устойчивостью кода.

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

При помощи предложения EXISTS вы выбираете всех клиентов, для которых существует хотя бы одна запись order_details.

SELECT * 
FROM customers c
WHERE EXISTS (SELECT * FROM order_details od WHERE od.customer_id = c.customer_id);

При объединении вы снова выбираете этих клиентов.Тем не менее, вы выбираете каждый из них так часто, как существует order_detail для них.Т.е. у вас будет много дубликатов.

SELECT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;

Вы можете удалить дубликаты из своих результатов с помощью DISTINCT, чтобы получить каждого клиента только еще раз:

SELECT DISTINCT c.*
FROM customers c
JOIN order_details od ON c.customer_id = od.customer_id;

Но почемусоздать все дубликаты только для того, чтобы снова их удалить?Не делай этого.Присоединяйтесь только тогда, когда вы действительно хотите объединить результаты.

Другой вариант, который я считаю даже более читабельным, чем предложение EXISTS, это, кстати, предложение IN.Это был бы мой способ написания запроса:

SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM order_details);
0 голосов
/ 14 декабря 2018

EXISTS() называется "полусоединением".Он начинает JOIN, но затем останавливается, когда находит первое совпадение.По этой причине EXISTS будет быстрее, чем любой эквивалент JOIN.

Кроме того, EXISTS( SELECT * ... WHERE ... ) на самом деле не заботится о *.Он будет использовать любой индекс, оптимальный для обнаружения наличия или отсутствия строк, соответствующих WHERE, затем возвращает 1 или 0 (что означает «истина» или «ложь»).

Конечно, если a LEFT JOIN вернет 0 или 1 строку, никогда больше, тогда разница в производительности невелика.За исключением того, что LEFT JOIN будет возвращать значения из таблицы.

0 голосов
/ 12 декабря 2018

EXISTS будет логически работать следующим образом

for x in (select * from customers)
loop
      -- check if x.customer_id exists in order_details table.    
      ---if yes 
          --output the customer tables row
      -- else 
         --ignore 
end if;
end loop;

Таким образом, в существующем запросе план, как правило, использует вложенный цикл (хотя и не является жестким правилом)

Запрос JOIN выполняет логический эквивалент следующим образом

for x in (select * from customers)
loop
  --for each row in customer 
  -- fetch records from order_details which match this condition
      select * from order_details where customer_id=x.customerid     
end loop;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...