СЛЕДУЕТ ПРИСОЕДИНЯЙТЕСЬ, используя ИЛИ - PullRequest
4 голосов
/ 04 августа 2009

Мне было интересно, как я мог бы вернуть результат самого левого условия в предложении OR, использованном в LEFT JOIN, если оба значения оцениваются как true.

Решения, с которыми я сталкивался до сих пор, включают использование оператора CASE в SELECT, это означает, что я отказался бы от предложения OR.

Другое решение связано с использованием оператора CASE в ORDER BY.

Существуют ли другие решения, которые могли бы сократить использование операторов CASE. Причина, по которой я спрашиваю, заключается в том, что или сейчас есть только два LEFT JOIN с, но со временем будет добавлено еще.

SELECT item.id,
       item.part_number,
       lang.data AS name,
       lang2.data AS description
  FROM item
       LEFT JOIN
       language lang
          ON     item.id = lang.item
             AND (lang.language = 'fr' OR lang.language = 'en')
       LEFT JOIN
       language lang2
          ON     item.id = lang2.item
             AND (lang2.language = 'fr' OR lang2.language = 'en')
 WHERE item.part_number = '34KM003KL'

Ответы [ 5 ]

7 голосов
/ 04 августа 2009

Похоже, вам нужно французское описание, если оно существует, в противном случае откройте его на английском.

SELECT  item.id,
        COALESCE(
        (
        SELECT  lang.data
        FROM    language l
        WHERE   l.item = i.id
                AND l.language = 'fr'
        ),
        (
        SELECT  lang.data
        FROM    language l
        WHERE   l.item = i.id
                AND l.language = 'en'
        )
        ) AS description
FROM    item i

, или это:

SELECT  item.id,
        COALESCE(lfr.data, len.data)
FROM    item i
LEFT JOIN
        language lfr
ON      lfr.item = i.id
        AND lfr.language = 'fr'
LEFT JOIN
        language len
ON      len.item = i.id
        AND len.language = 'en'

Первый запрос более эффективен, если велика вероятность нахождения описания на французском языке (он не оценивает второй подзапрос, если первый подан успешно).

В SQL Server, Oracle и PostgreSQL этот, вероятно, будет более эффективным, если у вас много французских описаний:

SELECT  item.id,
        COALESCE(
        lfr.data,
        (
        SELECT  lang.data
        FROM    language l
        WHERE   l.item = i.id
                AND l.language = 'en'
        )
        ) AS description
FROM    item i
LEFT JOIN
        language lfr
ON      lfr.item = i.id
        AND lfr.language = 'fr'

В этом запросе будет использован эффективный метод (HASH JOIN или MERGE JOIN), чтобы объединить описания на французском языке, и откроется английский только в случае необходимости.

Для MySQL запросы 1st и 3rd не имеют значения.

Во всех системах создайте составной индекс для language (item, language)

2 голосов
/ 04 августа 2009

Вы можете изменить несколько Ors, чтобы использовать вместо них предложение In ...

SELECT i.id, i.part_number, L1.data name, L2.data description 
FROM item i
   LEFT JOIN language L1 ON i.id = L1.item 
      AND L1.language In ('fr', 'en')
   LEFT JOIN language L2 ON i.id = L2.item 
      AND L2.language In ('fr', 'en')
WHERE i.part_number = '34KM003KL'
0 голосов
/ 04 августа 2009

Почему бы вам просто не выполнить свои критерии в предложении WHERE?

SELECT item.id, item.part_number, lang.data AS name, lang2.data AS description 
    FROM item AS item
    LEFT JOIN language AS lang ON item.id = lang.item 
    LEFT JOIN language AS lang2 ON item.id = lang2.item 
    WHERE item.part_number = '34KM003KL'
        AND (lang.language = 'fr' OR lang.language = 'en')
        AND (lang2.language = 'fr' OR lang2.language = 'en')
0 голосов
/ 04 августа 2009

Если вам нужен французский перевод, если он существует, и английский как второй вариант, вы можете присоединиться к языковой таблице один раз для каждого языка:

select
   item.id, item.part_number, isnull(fr.data, en.data) as name
from
   item
   left join language fr on fr.item = item.id and fr.language = 'fr'
   left join language en on en.item = item.id and en.language = 'en'
where
   item.part_number = '34KM003KL'
0 голосов
/ 04 августа 2009

Может быть, вы хотите что-то вроде этого:

SELECT item.id, item.part_number, COALESCE (lang.data, lang2.data) AS description 
FROM item AS item
LEFT JOIN language AS lang ON item.id = lang.item AND lang.language = 'fr'
LEFT JOIN language AS lang2 ON item.id = lang2.item AND lang2.language = 'en'
WHERE item.part_number = '34KM003KL'

Это вернет французские данные, если существует французский и английский, или если существует только французский.

...