SQL присоединиться: где предложение vs. по п

голоса
483

Прочитав его, это не дубликат Явные против неявных SQL присоединяется . Ответ может быть связан (или даже тот же) , но вопрос по - другому.


В чем разница и что должно пойти в каждом?

Если я понимаю теорию правильно, оптимизатор запросов должен быть в состоянии использовать как взаимозаменяемые.

Задан 09/12/2008 в 21:14
источник пользователем
На других языках...                            


14 ответов

голоса
640

Они не одно и то же.

Рассмотрим эти вопросы:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

а также

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

Первый возвращает порядок и его линии, если таковые имеются, по номеру заказа 12345. Второй возвращают все заказы, но только для того 12345будет иметь какую - либо линию , связанную с ним.

С INNER JOIN, что положения являются фактически эквивалентны. Тем не менее, только потому , что они функционально же, в том , что они дают одинаковые результаты, не означает , что эти два вида положений имеют одинаковую смысловую.

Ответил 09/12/2008 в 21:21
источник пользователем

голоса
154
  • Не имеет значения для внутренних соединений
  • Вопросы для внешних соединений

    а. WHEREпункт: После присоединения. Записи будут отфильтрованы после присоединиться имевшее место.

    б. ONпункт - До прихода. Записи (из таблицы справа) будет фильтроваться до прихода. Это может закончиться как нуль в результате (с OUTER присоединиться).



Пример : Рассмотрим следующие таблицы:

    1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

а) Внутри WHEREпункта:

  SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  | 

б) Внутри JOINпункта

  SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL | 
Ответил 07/01/2014 в 21:54
источник пользователем

голоса
137

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

На OUTER JOINх, они не обязательно являются взаимозаменяемыми, в зависимости от того, какая сторона объединения они зависят от.

Я положил их в любом месте, в зависимости от читаемости.

Ответил 09/12/2008 в 21:21
источник пользователем

голоса
30

Как мне сделать это:

Всегда ставить условие соединения в предложении на Если вы делаете внутреннее соединение, поэтому не добавляйте где условия к о п, положить их в ИНЕКЕ

Если вы делаете левый присоединиться, добавлять где условия к о п для таблицы в правой части соединения. Это необходимо потому, что добавление, где положение, которое ссылается на правую сторону объединения будет преобразовывать зарегистрироваться, чтобы внутреннее соединение (за одним исключением описанного ниже).

Исключением является то, что, когда вы ищете для записей, которые не в конкретной таблице, вы бы добавить Refernce к уникальному идентификатору (то есть никогда не нуль) в правом присоединиться таблицы, где положение таким образом, «где Т2. idfield равно нулю». Поэтому единственный раз, когда вы должны ссылаться на таблицу на правой стороне соединения, чтобы найти те записи, которые не находятся в таблице.

Ответил 09/12/2008 в 21:57
источник пользователем

голоса
29

На внутреннем соединении, они имеют в виду то же самое. Однако вы получите разные результаты внешнего соединения в зависимости от того, если вы поставите условие объединения в WHERE против оговорки ON. Взгляните на этом связанный с этим вопрос и этот ответ (на меня).

Я думаю, что это имеет больше смысла, чтобы быть в привычку всегда поставить условие объединения в предложении ON (если это не внешнее соединение, и вы на самом деле хотите в ИНЕКЕ), как это делает его более ясным для тех, кто читает ваш запрос какие условия столы соединены на, а также помогает предотвратить условие WHERE от того, десятки линий длиной.

Ответил 09/12/2008 в 21:20
источник пользователем

голоса
12

В этой статье четко объясняет разницу. Это также объясняет «ON joined_condition против ГДЕ joined_condition или joined_alias равна нулю».

ИНЕКЕ фильтры как левая и правая стороны соединения, в то время как положение ON всегда будет фильтровать только по правой стороне.

  1. Если вы хотите всегда получать левые боковые ряды и только JOIN, если какое-либо условие совпадает, то вы должны в положение ON.
  2. Если вы хотите, чтобы фильтровать продукт присоединения с обеих сторон, то вы должны использовать предложение WHERE.
Ответил 25/05/2014 в 15:20
источник пользователем

голоса
7

С точки зрения оптимизатора, он не должен сделать разницу вы определить, будут ли ваши присоединиться положения с ON или WHERE.

Однако, ИМХО, я думаю, что это гораздо яснее использовать положение ON при выполнении соединения. Таким образом, у вас есть конкретный раздел вам запрос, который определяет, как объединение обрабатывается по сравнению перемешано с остальным ИНЕК.

Ответил 09/12/2008 в 21:21
источник пользователем

голоса
5

Существует большая разница между ИНЕК VS. на пункте , когда речь идет налево присоединиться.

Вот пример:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

Там груда является идентификатор таблицы t2.

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

Запрос на «по статье»:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

Запрос на «где п»:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

Понятно, что первый запрос возвращает записи из t1 и зависимый строки из t2, если таковые имеются, для ряда t1.v = «K».

Второй запрос возвращает строку из t1, но только для t1.v = «K» будет иметь любую строку, связанную с ним.

Ответил 13/03/2016 в 06:31
источник пользователем

голоса
1

Обычно, фильтрация обрабатывается в предложении, где когда две таблицы уже присоединились. Вполне возможно, что, хотя вы можете отфильтровать один или оба из таблиц, прежде чем присоединиться к ним. то есть положение, где применяется ко всему результирующего набора, тогда как на пункте относится только к присоединиться к вопросу.

Ответил 16/02/2018 в 05:29
источник пользователем

голоса
1

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

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

так что вы JOIN с помощью индексированных столбцов, то после запуска РЕГИСТРИРУЙТЕСЬ условие на доли не индексируются столбца.

Ответил 12/12/2014 в 21:10
источник пользователем

голоса
0

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

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

Это (ИМХО) совершенно сбивает с толку человека, и это очень легко забыть связать table1к чему - либо (потому что «водитель» таблица не имеет «на» положение), но это законно.

Ответил 16/05/2014 в 23:40
источник пользователем

голоса
0

В SQL, положение в «WHERE» и «ON», своего рода условного Statemants, но главное различие между ними, «где» пункт используется в Select / Update отчетности для уточнения условий, в то время как п «на» используется в соединениях, где он проверяет или чеки, если отчеты подбираются в целевых и исходных таблиц, перед Таблицы Регистрация

Например: - «где»

SELECT * FROM сотрудника WHERE employee_id = 101

Например: - 'ON'

* Есть две таблицы сотрудников и employee_details, совпадающие столбцы EMPLOYEE_ID. *

SELECT * FROM сотрудник INNER JOIN employee_details ON employee.employee_id = employee_details.employee_id

Надеюсь, я ответил на ваш Question.Revert назад для уточнений.

Ответил 05/02/2014 в 11:57
источник пользователем

голоса
0

Я думаю, что это объединение последовательности эффект. В верхнем левом углу объединить дело, SQL сделать левый присоединиться к первой, а затем сделать где фильтр. В случае Даунер найти Orders.ID = 12345 первый, а затем сделать присоединиться.

Ответил 07/01/2014 в 04:49
источник пользователем

голоса
-5

это мое решение.

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

Вы должныGROUP BY , чтобы заставить его работать.

Надеюсь, что это поможет.

Ответил 26/04/2010 в 08:53
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more