2017-02-12 2 views
0

Я застреваю в запросе. Надеюсь, кто-то может помочь мне здесь.SQL. Left Join и Null значение, когда столбец не существует

У меня есть эти 4 таблицы:

Таблица: детали

id_items 
1 

Таблица: items_atr_currencies_match

id_items_atr_currencies_match | id_items_atr_currencies | id_items 
1        | 1      | 1 

Таблица: items_atr_currencies_translations

id_items_atr_currencies_translations | id_items_atr_currencies | id_language_code | translation 
1         | 1      | 1    | $ 

Таблица: items_atr_currencies

id_items_atr_currencies 
1 

Таблица: языки

id_languages | language_code 
1   | es 
2   | en 

Мой запрос:

SELECT 
    id_items, 
    iact3.translation AS currency 

FROM 
    items i 

LEFT JOIN 
    items_atr_currencies_match AS iacm3 ON iacm3.id_items = i.id_items 
LEFT JOIN 
    items_atr_currencies AS iac3 ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies 
LEFT JOIN 
    items_atr_currencies_translations AS iact3 ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies 
LEFT JOIN 
    languages AS l ON l.id_languages = iact3.id_language_code OR iact3.id_language_code IS NULL 

WHERE 
    i.id_items = 1 
    AND l.language_code = "en" 

Ожидаемый результат:

id_items | currency 
1  | null 

Получение 0 результат вместо

Я думаю, что у меня отсутствует что-то вроде «ИЛИ iact3.id_language_code не существует» в последней ЛЕВЫМ СОЕДИНЕНИЕМ, но я не знаю, как это сделать.

Он отлично работает, когда таблица items_atr_currencies_match не имеет данных или когда таблица items_atr_currencies_translations имеет перевод, но не тогда, когда есть данные, и перевод не существует.

Спасибо заранее

* UPDATE *

Наконец этот запрос делает то, что я хочу:

SELECT 
    i.id_items,    
    iact3.translation AS currency 

FROM 
    items i 

LEFT JOIN 
    languages AS l ON l.language_code = 'en' 
LEFT JOIN 
    items_atr_currencies_match AS iacm3 ON iacm3.id_items = i.id_items 
LEFT JOIN 
    items_atr_currencies_translations AS iact3 ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies 
    AND l.id_languages = iact3.id_language_code    
LEFT JOIN items_atr_currencies AS iac3 ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies 

WHERE 
    i.id_items = 1 

Все, что я должен был сделать, это переместить язык LEFT JOIN к и найдите там код языка.

+0

Вы, вероятно, нужно переместить последнее условие в объединение: 'LEFT JOIN языки AS л о l.id_languages ​​= iact3.id_language_code И l.language_code = "EN" ГДЕ i.id_items = 1'. Основное правило для Внешних объединений: conditons на внешней таблице обычно являются частью WHERE, а условия для внутренней таблицы добавляются в 'ON' – dnoeth

+0

Привет @dnoeth, я получаю результат« 1 | $ », но перевод« en »не выполняется 't выходы. Не следует получать 1 | null вместо? Это то, что я ожидаю. Спасибо –

ответ

0

Вам необходимо переместить состояние AND l.language_code = "en" в левое соединение. В противном случае это условие будет проверяться после того, как все левые соединения будут оценены, и если тогда полученный кортеж не имеет language_code = "en", он будет исключен из общего результата.

Если вы теперь хотите, чтобы currencies_translations считается только, если они соответствуют правильному языку, чем вы должны соединить currencies_translations и languages от объединения, прежде чем «левое присоединение» вместе с Overal результата:

... 
LEFT JOIN (select iact3.id_items_atr_currencies as iact3id from 
    items_atr_currencies_translations AS iact3 JOIN 
    languages AS l ON (l.id_languages = iact3.id_language_code AND l.language_code = "en") OR iact3.id_language_code IS NULL) as iact3l 
    ON iact3l.iact3id = iacm3.id_items_atr_currencies 
+0

Спасибо за ответ @stepahnLechner, теперь я получаю результаты, но я не получаю правильный результат. Я получаю: 'id_items | Валюта '' 1 | $ ', и поскольку этот перевод не существует, я ожидал:' id_items | Валюта '' 1 | null', любое предложение? Спасибо –

+0

Я полагаю, что вам нужно обрабатывать 'currencies_translations' и' languages' как «совместный промежуточный результат», который затем может быть рассмотрен чрезмерным запросом в виде левого сустава. См. Отредактированный ответ. Надеюсь, что это работает напрямую или с некоторыми небольшими модификациями синтаксиса ... –

+0

... И «$» в результате, потому что на самом деле существует запись 'items_atr_currencies_translations', которая не отфильтрована, поскольку ее (не существующее) соединение с 'language' просто« левый присоединился »... –

0

У вас есть серия left join s. Когда у вас есть условие в предложении where в любой таблице , кроме первой таблицы, тогда она имеет тенденцию превращать left join в inner join. Вам нужно положить, что условие в предложении on:

SELECT id_items,iact3.translation AS currency 
FROM items i LEFT JOIN 
    items_atr_currencies_match AS iacm3 
    ON iacm3.id_items = i.id_items LEFT JOIN 
    items_atr_currencies AS iac3 
    ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies LEFT JOIN 
    items_atr_currencies_translations AS iact3 
    ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies LEFT JOIN 
    languages AS l 
    ON (l.id_languages = iact3.id_language_code OR iact3.id_language_code IS NULL) AND 
     l.language_code = 'en' 
WHERE i.id_items = 1; 

условия на первой таблице идут в пункте WHERE.

Примечания: Я думаю, что последнее условие может быть упрощено:

 ON l.id_languages = iact3.id_language_code AND 
     l.language_code = 'en' 

LEFT JOIN будет включать в себя ряд, даже если нет никакого совпадения.

+0

Спасибо за ответ, теперь я получаю результаты, но я не получаю правильный результат. Я получаю: 'id_items | валюта '1 | $ ' и с тех пор перевода не существует Я ожидал: ' id_items | валюта '1 | null' Спасибо –

Смежные вопросы