Использование левого соединения и внутреннего соединения в одном запросе

Ниже мой запрос использует левое соединение, которое работает так, как ожидалось. То, что я хочу сделать, это добавить еще один фильтр для фильтрации этого запроса, но у него проблемы с этим. Я буду называть эту новую таблицу 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 получает синтаксическую ошибку.

Ответ 1

Помните, что фильтрация правой таблицы в левом соединении должна выполняться в самом соединении.

select *
from table1 
  left join table2
    on table1.FK_table2 = table2.id
    and table2.class = 'HIGH'

Ответ 2

Добавьте свой 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)

Ответ 3

Я, наконец, понял это. Спасибо за вашу помощь!!!

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

Ответ 4

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

  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 = '') 

Ответ 5

Я не уверен, чего ты хочешь. Но может быть что-то вроде этого:

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 = '') 

Ответ 6

Я всегда сталкиваюсь с этим вопросом, когда ищу, как сделать так, чтобы 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 также найден.

Ответ 7

Для Postgres планировщик запросов не гарантирует порядок выполнения объединения. Чтобы гарантировать, можно использовать решение @Gajus, но проблема возникает, если есть условие Where для столбцов внутренней таблицы. Либо может потребоваться аккуратно добавить предложения where в соответствующее условие Join, либо иным способом лучше использовать подзапрос внутренней части соединения, а слева - присоединение к выводу.