Ответ 1
Помните, что фильтрация правой таблицы в левом соединении должна выполняться в самом соединении.
select *
from table1
left join table2
on table1.FK_table2 = table2.id
and table2.class = 'HIGH'
Ниже мой запрос использует левое соединение, которое работает так, как ожидалось. То, что я хочу сделать, это добавить еще один фильтр для фильтрации этого запроса, но у него проблемы с этим. Я буду называть эту новую таблицу table_3
и хочу добавить где table_3.rwykey = runways_updatable.rwykey
. Любая помощь будет очень оценена.
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
' ************* РЕДАКТИРОВАТЬ К РАЗЛИЧЕНИЮ ***************** > Вот еще одно выражение, что внутреннее соединение, которое я хотел бы использовать, и я хотел бы объединить эти 2 утверждения.
SELECT *
FROM RUNWAYS_UPDATABLE A, RUNWAYS_TABLE B
WHERE A.RWYKEY = B.RWYKEY
' ** * Что я имею в виду, как совет, приведенный ниже, но получение синтаксической ошибки
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*, AIRPORT_RUNWAYS_SELECTED.*
FROM RUNWAYS_UPDATABLE
INNER JOIN AIRPORT_RUNWAYS_SELECTED
ON RUNWAYS_UPDATABLE.RWYKEY = AIRPORT_RUNWAYS_SELECTED.RWYKEY
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
ПРИМЕЧАНИЕ. Если я прокомментирую внутреннее соединение и оставьте левое соединение или наоборот, оно работает, но когда у меня есть оба соединения в запросе, это когда im получает синтаксическую ошибку.
Помните, что фильтрация правой таблицы в левом соединении должна выполняться в самом соединении.
select *
from table1
left join table2
on table1.FK_table2 = table2.id
and table2.class = 'HIGH'
Добавьте свой INNER_JOIN
перед тем, как LEFT JOIN
:
SELECT *
FROM runways_updatable ru
INNER JOIN table_3 t3 ON ru.rwykey = t3.rwykey
LEFT JOIN turn_updatable tu
ON ru.rwykey = tu.rwykey
AND (tu.airline_code IS NULL OR tu.airline_code = '' OR tu.airline_code = '')
WHERE ru.icao = 'ICAO'
AND (ru.tora > 4000 OR ru.lda > 0)
Если вы LEFT JOIN
перед вашим INNER JOIN
, то вы не получите результаты от table_3
, если в turn_updatable
нет соответствующей строки. Возможно, это то, что вы хотите, но поскольку ваше условие соединения для table_3
относится только к ссылкам runways_updatable
, я бы предположил, что вы хотите получить результат от table_3
, даже если в turn_updatable
нет соответствующей строки.
ИЗМЕНИТЬ
Как отметил NikolaMarkovinović, вы должны отфильтровать ваш LEFT JOIN
в условии соединения, как вы видите выше. В противном случае вы не получите результаты из таблицы слева (runways_updatable
), если это условие не выполняется в правой таблице (turn_updatable
).
EDIT 2: OP упомянул, что это фактически Access, а не MySQL
В Access, возможно, это разница в псевдонимах таблицы. Вместо этого попробуйте:
SELECT [ru].*, [tu].*, [ars].*
FROM [runways_updatable] AS [ru]
INNER JOIN [airport_runways_selected] AS [ars] ON [ru].rwykey = [ars].rwykey
LEFT JOIN [turn_updatable] AS [tu]
ON [ru].rwykey = [tu].rwykey
AND ([tu].airline_code IS NULL OR [tu].airline_code = '' OR [tu].airline_code = '')
WHERE [ru].icao = 'ICAO'
AND ([ru].tora > 4000 OR [ru].lda > 0)
Я, наконец, понял это. Спасибо за вашу помощь!!!
SELECT * FROM
(AIRPORT_RUNWAYS_SELECTED
INNER JOIN RUNWAYS_UPDATABLE
ON AIRPORT_RUNWAYS_SELECTED.RWYKEY = RUNWAYS_UPDATABLE.RWYKEY)
LEFT JOIN TURN_UPDATABLE ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
Если это просто внутреннее соединение, которое вы хотите добавить, сделайте это. Вы можете добавить столько же, сколько хотите в одном запросе. Обновите свой ответ, если это не то, что вы хотите, хотя
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
INNER JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
Я не уверен, чего ты хочешь. Но может быть что-то вроде этого:
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*
FROM RUNWAYS_UPDATABLE
JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
Я всегда сталкиваюсь с этим вопросом, когда ищу, как сделать так, чтобы LEFT JOIN
зависел от дальнейшего INNER JOIN
. Вот пример того, что я ищу, когда я ищу "используя LEFT JOIN
и INNER JOIN
в одном запросе":
SELECT *
FROM foo f1
LEFT JOIN (bar b1
INNER JOIN baz b2 ON b2.id = b1.baz_id
) ON
b1.id = f1.bar_id
В этом примере b1
будет включен, только если b2
также найден.
Для Postgres планировщик запросов не гарантирует порядок выполнения объединения. Чтобы гарантировать, можно использовать решение @Gajus, но проблема возникает, если есть условие Where для столбцов внутренней таблицы. Либо может потребоваться аккуратно добавить предложения where в соответствующее условие Join, либо иным способом лучше использовать подзапрос внутренней части соединения, а слева - присоединение к выводу.