|
Для SELECT * FROM TableA a JOIN TableB b ON аргументы за a.col = b.col и за b.col = a.col
|
|||
---|---|---|---|
#18+
С точки зрения производительности оба варианта равноценны. Код: sql 1. 2.
А вот с точки зрения логики запроса, удобства воприятия и написания кто что себе на этот счёт думает? Первый вариант - условно говоря, поля в сравнении появляются в порядке появления таблиц в запросе, а второй - сначала названо поле присоединяемой таблицы, и затем оно сравнивается с полями из уже описанной на этот момент выборки ... |
|||
:
Нравится:
Не нравится:
|
|||
11.06.2020, 12:40 |
|
Для SELECT * FROM TableA a JOIN TableB b ON аргументы за a.col = b.col и за b.col = a.col
|
|||
---|---|---|---|
#18+
Некоторое гугление на данную тему дало следующее: https://postgrespro.ru/docs/postgresql/9.6/queries-table-expressions - дока по Постгресу - говорит просто: пишите там сравнения. И приводит пример с полями в порядке упоминания таблиц https://docs.microsoft.com/ru-ru/sql/relational-databases/performance/joins?view=sql-server-ver15 - MS SQL Server - так же. https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj18922.html - так же, но в примерах ещё и нарочитое разнообразие - в первом с алиасами и в порядке по второму моему образцу, во втором - без алиасов, и в порядке по первому образцу. Да ещё и регистр скачет как хочет. https://www.oracletutorial.com/oracle-basics/oracle-left-join/ - сайт обучающий про Оракл - тоже разнообразие наблюдается. К тому же тут пишут The query compares each row in the T1 table with rows in the T2 table., хотя на самом деле всё наоборот, и правильно было б The query compares rows in the T2 table with each row in the T1 table. Нашёлся и аналогичный вопрос на SO - https://stackoverflow.com/questions/24428427/best-practices-for-the-order-of-joined-columns-in-a-sql-join - там я отписался с аргументом в пользу второго, а до меня - кто-то отписался в пользу второго, но сослался на вкусы и не аргументировал, кто-то отписался в пользу первого, сказав что его так учили, и двое ответили не в тему, сказав что на производительность не влияет. Ещё я попробовал почитать стандарт http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt, дык там так мудрёно написано, что я не пойму, касаются ли они вообще этого вопроса (( ... |
|||
:
Нравится:
Не нравится:
|
|||
11.06.2020, 12:58 |
|
Для SELECT * FROM TableA a JOIN TableB b ON аргументы за a.col = b.col и за b.col = a.col
|
|||
---|---|---|---|
#18+
Ещё интересный аспект здесь - а что с другими видами JOIN? Что такое вообще JOIN в логике SQL-запроса? Запрос строит выборку. Выборка в запросе описывается последовательно, на языке, практически читаемом как цельная понятная фраза: мы SQL-машине, фактически, говорим строить итоговую выборку, взяв строки вот отсюда, а ещё подключить к ним строки ещё и отсюда, и ещё вот отсюда и т.п. То есть, JOIN - это операция добавления ещё одной группы строк к уже собранной предыдущими инструкциями группе строк. Когда джойним очередную таблицу, можно сказать что мы добавляем эту одну таблицу к уже собранной выборке. То есть, для каждого JOIN у нас на входе есть уже отобранная выборка (всё, что получилось в итоге сборки всего что выше по тексту запроса), есть добавляемая таблица и в итоге на выходе из каждого JOIN получается его итоговая выборка , которая станет исходной выборкой для следующего JOIN, если такой в запросе есть. Оптимизатор SQL-машины, конечно, может всё это выполнять в другом порядке, и скорее всего каждую промежуточную выборку вовсе не будет формировать отдельно, но с точки зрения логики написания запроса - всё именно так. Теперь про виды JOIN-ов. Как выполняется запрос при LEFT JOIN ? Для каждой записи уже отобранной выборки ищутся записи в добавляемой таблице, и если такие есть - она сопоставляется каждой из них, и полученное добавляется в итоговую выборку, если нет - итоговая выборка дополняется строкой с null-ами, и запись исходной выборки сопоставляется с ней. Записи добавляемой таблицы, для которых в исходной выборке соответствия не нашлось, в итоговую выборку не попадают. Таким образом, мы в описании добавления таблицы указываем, какие именно записи добавляемой таблицы должны найтись, чтоб пополнить выборку. Мы говорим про очередную запись из добавляемой таблицы и накладываем условие именно на неё. И в первом варианте получается фраза типа: Давайте позовём Васю. Какого? Ну, вот у Пети он друг, и светлые волосы у этого Васи, и много денег тоже у этого Васи. А во втором - вот так: Давайте позовём Васю. Какого? Ну, тот Вася который друг Пети, у которого светлые волосы и у которого много денег. Второе - органичнее, нет? Условие для простого JOIN, без приписок (того, который допускает бесполезную приписку INNER ) - всё ровно так же, только при отсутствии записи в добавляемой таблице запись исходной выборки пропускается. Условие, фактически, можно читать ровно так же, как читается условие для LEFT. Как выполняется запрос при RIGHT JOIN ? Для каждой записи добавляемой таблицы ищутся записи в уже отобранной выборке, и если такие есть - она сопоставляется им и добавляется в итоговую выборку, если нет - итоговая выборка дополняется строкой с null-ами, и запись добавляемой таблицы сопоставляется ей. Записи исходной выборки, для которых в добавляемой таблице соответствия не нашлось, в итоговую выборку не попадают. Таким образом, для right join условие логично записать про соответствие выборки добавляемой таблице, то есть в выражениях поля выборки указывать слева, а поля добавляемой таблицы справа. А что с FULL JOIN ? Там исходная выборка и добавляемая таблица симметричны, обе дополняются пустыми полями если не найдено встречной записи, но если участь, что мы всё ж к выборке добавляем что-то новое, логично про это новое и что-либо утверждать, то есть условие логично писать как для LEFT JOIN. Для CROSS JOIN условий нет, и вопроса нет. Но логика ровно та же - идём по выборке, и для каждой записи ходим по добавляемой таблице. ИТОГО: Всё кроме RIGHT JOIN, логично укладывается во второй образец. (Я вообще считаю, что right join вообще излишество, наляпанное чисто для симметрии! Он скорее вреден, чем полезен.) И меня чрезвычайно удивляет, почему столь популярен первый. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.06.2020, 13:49 |
|
|
start [/forum/topic.php?fid=56&msg=39968190&tid=2015020]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
386ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
35ms |
get tp. blocked users: |
2ms |
others: | 234ms |
total: | 704ms |
0 / 0 |