Объединяет с WHERE - разделение предложений WHERE - PullRequest
0 голосов
/ 07 октября 2018

Я решил запрос по этой ссылке

Можете ли вы вернуть список персонажей и сериалов, которые не названы «Уиллоу Розенберг» и отсутствуют в шоу «КакЯ встретил вашу маму "?

со следующим кодом:

SELECT ch.name,sh.name
FROM character ch 
  INNER JOIN character_tv_show chat
                 ON ch.id = chat.character_id
                      INNER JOIN tv_show sh
                                     ON chat.tv_show_id=sh.id
                                     WHERE ch.name != "Willow Rosenberg" AND sh.name !="How I Met Your Mother"
;

Однако моя первая попытка была:

SELECT ch.name,sh.name
FROM character ch 
WHERE ch.name != "Willow Rosenberg" /*This here*/
  INNER JOIN character_tv_show chat
                 ON ch.id = chat.character_id
                      INNER JOIN tv_show sh
                                     ON chat.tv_show_id=sh.id
                                     WHERE sh.name !="How I Met Your Mother"
;

, потому что я думал, что втаким образом, только таблица character была бы отфильтрована перед выполнением объединений и, следовательно, была бы менее сложной в вычислительном отношении.

Имеет ли это какой-то смысл?

Есть ли способ "разделить" предложение WHERE при объединении нескольких таблиц?

Ответы [ 4 ]

0 голосов
/ 07 октября 2018

A SELECT может содержать только 1 WHERE предложение.
И оно идет после JOIN.

Но у вас могут быть дополнительные предложения WHERE в подзапросах, к которым вы присоединяетесь.

И иногда критерии, добавленные вами к предложению WHERE, можно переместить в ON для JOIN.

Например, приведенные ниже запросы будут возвращать те же результаты

SELECT *
FROM Table1 AS t1
JOIN Table2 AS t2 ON t2.ID = t1.table2ID
WHERE t1.Col1 = 'foo'
AND t2.Col1 = 'bar'

SELECT *
FROM 
(
   SELECT * 
   FROM Table1 
   WHERE Col1 = 'foo'
) AS t1
JOIN Table2 AS t2 ON t2.ID = t1.table2ID
WHERE t2.Col1 = 'bar'

SELECT *
FROM Table1 AS t1
JOIN Table2 AS t2 ON (t2.ID = t1.table2ID AND t2.Col1 = 'bar')
WHERE t1.Col1 = 'foo'
0 голосов
/ 07 октября 2018

Думайте о JOIN s как о перекрестном произведении двух таблиц, которое фильтруется с использованием условий, указанных в предложении ON.Ваше предложение WHERE затем применяется к набору результатов, а не к отдельным таблицам, участвующим в объединении.

enter image description here

Если вы хотите применитьWHERE только для одной из соединенных таблиц, вам нужно будет использовать подзапрос.Отфильтрованный результат этого подзапроса будет затем обрабатываться как обычная таблица и объединяться с таблицей real , снова используя JOIN.

Если вы делаете это для повышения производительности, помните, чточто объединение почти всегда быстрее в стандартных JOIN s по сравнению с подзапросами для правильно проиндексированных таблиц.Вы обнаружите, что запросы, использующие JOIN, будут на несколько порядков быстрее, чем запросы, использующие подзапросы, за исключением редких случаев.

0 голосов
/ 07 октября 2018
Предложения

JOIN и WHERE не обязательно выполняются в том порядке, в котором вы их пишете.В общем, оптимизатор запросов будет перестраивать вещи, чтобы сделать их максимально эффективными (или, по крайней мере, то, что он считает наиболее эффективным), поэтому добавление второго предложения WHERE не будет отличаться от добавления другого условия AND (вот почему это не разрешено).

Ваша идея не была плохой, но дело не в том, как на самом деле работают базы данных.

0 голосов
/ 07 октября 2018

Вы можете использовать подзапросы

SELECT ch.name,sh.name
  FROM (
        SELECT ch.name
        FROM character ch 
        WHERE ch.name != "Willow Rosenberg") ch
  INNER JOIN character_tv_show chat
             ON ch.id = chat.character_id
  INNER JOIN tv_show sh
             ON chat.tv_show_id=sh.id
  WHERE sh.name !="How I Met Your Mother"

, но я думаю, что это не имеет смысла.подзапросы составят временную таблицу.Первый запрос будет оптимизирован сервером базы данных и, вероятно, выберет только те строки из таблицы символов, которые нуждаются в

...