Вы также получите эту ошибку, если забудете new
:
String s = String();
в сравнении с
String s = new String();
Единственная причина, по которой я могу думать о том, чтобы использовать RIGHT OUTER JOIN, - это попытаться сделать ваш SQL более самодокументированным.
Возможно, вы захотите использовать левые соединения для запросов с нулевыми строками в зависимая (много) сторона отношений «один ко многим» и правильное объединение по тем запросам, которые генерируют нулевые строки в независимой стороне.
Это также может происходить в сгенерированном коде или если требования к кодированию магазина определяют порядок объявления таблиц в предложении FROM.
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col
Замените [BLANK] на:
LEFT - если вы хотите, чтобы все записи из таблицы1 даже если у них нет col, который соответствует таблице2 (также включены записи таблицы2 со спичками)
RIGHT - если вы хотите, чтобы все записи из таблицы2, даже если у них нет col, который соответствует таблице1 (также включены записи таблицы 1 со спичками)
FULL - если вы хотите, чтобы все записи из таблицы1 и из таблицы2
О чем все говорят? Они такие же? Я так не думаю.
Единственный раз, когда я думаю о правильном внешнем соединении, - это если я исправляю полное соединение, и так получилось, что мне нужен результат, чтобы содержать все записи из таблицы справа. Хотя, хотя и ленивый, как я, мне было бы так досадно, что я перестрою его, чтобы использовать левое соединение.
Этот пример из Wikipedia показывает, что я имею в виду:
SELECT *
FROM employee
FULL OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID
Если вы просто замените слово FULL
на RIGHT
, у вас есть новый запрос, не заменяя порядок предложения ON
.
FULL
имеет свою цель и не всегда нуждается в «фиксации» и заменяет его на RIGHT
, не делает то же самое. Что делать, если вы создаете отчет, чтобы помочь компании утвердить назначения сотрудников и отделов, и хотите включить отделы, у которых нет сотрудников, а также сотрудников, которые не были назначены отделу?
– utexaspunk
12 February 2014 в 17:51
Операторы SQL, в дополнение к правильности, должны быть максимально просты в чтении и выразительном сжатии (поскольку они представляют собой одиночные атомарные действия, и ваш ум должен полностью их убеждать, чтобы избежать непредвиденных последствий.) Иногда выражение больше четко обозначается правым внешним соединением.
Но всегда можно преобразовать в другое, и оптимизатор будет делать то же самое с другим, как и другим.
. Некоторое время, по крайней мере, один из основных продуктов rdbms поддерживает только LEFT OUTER JOIN. (Я считаю, что это был MySQL.)
Единственные времена, когда я использовал правильное соединение, были, когда я хочу посмотреть два набора данных, и у меня уже есть соединения в определенном порядке для левого или внутреннего соединения из ранее написанного запроса. В этом случае, скажем, вы хотите видеть в качестве одного набора данных записи, не включенные в таблицу a, а в таблицу b, а в другом - записи не в таблице b, а в таблице a. Даже тогда я, как правило, делаю это, чтобы сэкономить время на исследование, но изменил бы его, если бы это был код, который будет запускаться более одного раза.
Я думаю, что это сложно, если вы не имеете права присоединиться к этому делу. ex с оракулом.
with a as(
select 1 id, 'a' name from dual union all
select 2 id, 'b' name from dual union all
select 3 id, 'c' name from dual union all
select 4 id, 'd' name from dual union all
select 5 id, 'e' name from dual union all
select 6 id, 'f' name from dual
), bx as(
select 1 id, 'fa' f from dual union all
select 3 id, 'fb' f from dual union all
select 6 id, 'f' f from dual union all
select 6 id, 'fc' f from dual
)
select a.*, b.f, x.f
from a left join bx b on a.id = b.id
right join bx x on a.id = x.id
order by a.id
select a.*, b.f, x.f from bx x left outer join a on a.id = x.id left join bx b on b.id = a.id order by a.id
– JohnLBevan
30 November 2017 в 18:06
В некоторых базах данных SQL есть подсказки оптимизатора, которые сообщают оптимизатору о соединении таблиц в том порядке, в котором они появляются в предложении FROM
- например, /*+ORDERED */
в Oracle. В некоторых простых реализациях это может быть даже единственным доступным планом выполнения.
В таких случаях порядок таблиц в предложении FROM
имеет значение, так что RIGHT JOIN
может быть полезным.
SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....
Как еще вы могли бы быстро / легко встроить первые 2 таблицы и присоединиться к table_c, гарантируя, что все строки в таблице_c всегда выбраны?
SELECT * FROM table_c LEFT JOIN ( SELECT * FROM table_a INNER JOIN table_b ON .... ) ON ....
– 8forty
1 January 2018 в 21:15
Мне действительно не приходилось много думать о правильном объединении, но я полагаю, что мне не удалось почти 20 лет писать SQL-запросы, найти обоснованное обоснование для его использования. Я, конечно, видел много их, я думаю, из-за того, что разработчики использовали встроенные построители запросов.
Всякий раз, когда я сталкивался с ним, я переписал запрос, чтобы его устранить. Я обнаружил, что они требуют слишком много дополнительной умственной энергии для изучения или повторного изучения, если вы не посетили запрос в течение некоторого времени, и это не было редкостью в том, что цель запроса потерялась или вернуть неверные результаты - и обычно эта некорректность привела к тому, что я спросил, почему запросы не работают.
Подумав об этом, как только вы введете правое соединение, у вас теперь есть то, что я считаю конкурирующими ветвями логики, которые должны встречаться посередине. Если будут введены дополнительные требования / условия, обе эти ветви могут быть дополнительно расширены, и теперь у вас есть больше сложностей, связанных с жонглированием, чтобы одна ветка не приводила к неправильным результатам.
Далее , как только вы введете правильное соединение, другие менее опытные разработчики, которые работают над запросом позже, могут просто подключить дополнительные таблицы к правой части запроса и тем самым расширить конкурирующие логические потоки, которые все еще должны встречаться в средний; или в некоторых случаях, которые я видел, начинают вложенные представления, потому что они не хотят касаться исходной логики, возможно, частично, потому что они могут не понимать запрос или бизнес-правила, которые были на месте, которые приводили логику.
B ПРАВОЕ СОЕДИНЕНИЕ A такое же, как A LEFT JOIN B
B ПРАВОЕ СОЕДИНЕНИЕ A гласит: B ON RIGHT, THEN JOINS A. означает, что A находится в левой части набора данных. точно так же, как A LEFT JOIN B
Нет производительности, которую можно получить, если вы измените LEFT JOINs на RIGHT.
Единственные причины, по которым я могу подумать, почему use RIGHT JOIN - это если вы тип человека, который любит думать изнутри (выберите * from detail right join header).
Другим является то, что у вас уже есть обширный запрос, в котором вы хотите добавить еще один стол, когда это боль в шее, чтобы переупорядочить запрос, поэтому просто подключите таблицу к существующему запросу, используя ПРАВИЛЬНЫЙ JOIN.
Раньше я никогда не использовал right join
и никогда не думал, что на самом деле мне это может понадобиться, и кажется немного неестественным. Но после того, как я подумал об этом, это может быть действительно полезно в ситуации, когда вам нужно внешнее соединение одной таблицы с пересечением многих таблиц, поэтому у вас есть такие таблицы:
[/g0]
И хочу получить такой результат:
[/g1]
Или, в SQL (MS SQL Server):
declare @temp_a table (id int)
declare @temp_b table (id int)
declare @temp_c table (id int)
declare @temp_d table (id int)
insert into @temp_a
select 1 union all
select 2 union all
select 3 union all
select 4
insert into @temp_b
select 2 union all
select 3 union all
select 5
insert into @temp_c
select 1 union all
select 2 union all
select 4
insert into @temp_d
select id from @temp_a
union
select id from @temp_b
union
select id from @temp_c
select *
from @temp_a as a
inner join @temp_b as b on b.id = a.id
inner join @temp_c as c on c.id = a.id
right outer join @temp_d as d on d.id = a.id
id id id id
----------- ----------- ----------- -----------
NULL NULL NULL 1
2 2 2 2
NULL NULL NULL 3
NULL NULL NULL 4
NULL NULL NULL 5
Итак, если вы переключитесь на left join
, результаты не будут одинаковыми.
select *
from @temp_d as d
left outer join @temp_a as a on a.id = d.id
left outer join @temp_b as b on b.id = d.id
left outer join @temp_c as c on c.id = d.id
id id id id
----------- ----------- ----------- -----------
1 1 NULL 1
2 2 2 2
3 3 3 NULL
4 4 NULL 4
5 NULL 5 NULL
Единственный способ сделать это без правильного соединения - использовать общее выражение таблицы или подзапрос
select *
from @temp_d as d
left outer join (
select *
from @temp_a as a
inner join @temp_b as b on b.id = a.id
inner join @temp_c as c on c.id = a.id
) as q on ...
FROM @temp_d AS d LEFT OUTER JOIN (temp_a AS a INNER JOIN @temp_b AS b ON b.id = a.id INNER JOIN @temp_c AS c ON c.id = a.id) ON a.id = d.id
. (Скобки не нужны, они добавляются только для удобства чтения). Правда, есть люди, которые не определились в отношении того, какой синтаксис они предпочитают больше, вложенные объединения или внешние внешние соединения, поэтому возможно, что правильные объединения могут работать < i> менее плохо i> для них. :)
– Andriy M
16 March 2016 в 13:35