Подтвердить что ты не робот

SQL, соединяющий три таблицы, приоритет объединения

У меня есть три таблицы: R, S и P.

Таблица R Соединения с S через внешний ключ; в S должна быть хотя бы одна запись, поэтому я могу ПРИСОЕДИНЯЙСЯ:

SELECT
        *
    FROM 
        R
    JOIN    S ON (S.id = R.fks)

Если в S нет записи, тогда я не получаю никаких строк, это прекрасно.

Затем таблица S соединяется с P, где записи P могут или не могут присутствовать и соединяться с S.

Итак, я делаю

SELECT
        *
    FROM 
        R
    JOIN    S ON (S.id = R.fks)
    LEFT JOIN P ON (P.id = S.fkp)

Что, если бы я хотел, чтобы второй JOIN был привязан к S не к R, например, если бы я мог использовать круглые скобки:

SELECT
        *
    FROM 
        R
    JOIN    (S ON (S.id = R.fks) JOIN P ON (P.id = S.fkp))

Или это уже естественное поведение декартова произведения между R, S и P?

4b9b3361

Ответ 1

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

(Пример PostgreSQL)

В SELECT * FROM a LEFT JOIN b ON (a.id = b.id) JOIN c ON (b.ref = c.id);

ab-соединение вступает в силу первым, но мы можем заставить bc-соединение вступить в силу первым, поместив его в скобки, который выглядит следующим образом:

SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

Часто вы можете выразить то же самое без лишних скобок, перемещая соединения и изменяя направление внешнего соединения, например

SELECT * FROM b JOIN c ON (b.ref = c.id) RIGHT JOIN a ON (a.id = b.id);

Ответ 2

Когда вы присоединяетесь к третьей таблице, ваш первый запрос

SELECT
        *
    FROM 
        R
    JOIN    S ON (S.id = R.fks)

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

Итак, если вы ищете правила приоритета, тогда в этом случае он просто устанавливается с помощью LEFT JOIN в отличие от JOIN.

Однако я могу не понимать ваш вопрос, потому что, если бы я писал запрос, я бы обменивал S и R вокруг. например.

SELECT
        *
    FROM 
        S
    JOIN    R ON (S.id = R.fks)

Ответ 3

Второе соединение привязано к S как состояние экспликации JOIN P ON (P.id = S.fkp) - ни один столбец из R не упоминается в соединении.

Ответ 4

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

Ответ 5

with a as (select 1 as test union select 2)
select * from a left join
a as b on a.test=b.test and b.test=1 inner join
a as c on b.test=c.test 
go
with a as (select 1 as test union select 2)
select * from a inner join
a as b on a.test=b.test  right join
a as c on b.test=c.test and b.test=1

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