Предисловие: Я боюсь, что я прошу сделать то, чего не может быть достигнуто. Но я знаю, что, если есть способ сделать это, здесь кто-то будет знать :)
Предположим, у меня есть база данных MySQL (или MariaDB, если совместимость может быть сохранена). Мне нужно выбрать из TableA и присоединиться к TableB на основе определенного столбца, имеющего определенное значение X; возможно, в таблице Б нет подходящей строки, что означает, что я буду использовать ЛЕВЫЙ ВНЕШНИЙ СОЕДИНЕНИЕ. Однако, если ни одна строка не найдена (ни одна строка TableB не имеет значения X в этом столбце), то я хочу использовать строку из TableB со значением Y. Другими словами, Y должен действовать как условие возврата для JOIN.
Вот мой конкретный пример. Предположим, что я обрабатываю локализацию данных путем разделения объекта (например, продукта) между двумя таблицами, один с локализуемыми данными, а другой с фиксированными данными. Когда я хочу получить информацию о продукте на французском языке, я хочу вернуться на английский язык, если на французском языке информации нет. Однако, если я это сделаю
// basic stub of the query for demonstration purposes
SELECT * FROM Products p
LEFT OUTER JOIN ProductsLocalization pLoc
ON pLoc.ProductID = p.ID AND pLoc.Culture = 'fr-FR'
Я получу NULL, если никакая французская информация недоступна. Вместо этого, только для этих строк, я хочу получить результат запроса
// basic stub of the query for demonstration purposes
SELECT * FROM Products p
LEFT OUTER JOIN ProductsLocalization pLoc
ON pLoc.ProductID = p.ID AND pLoc.Culture = 'en-US'
Но, конечно, последний запрос неприемлем.
Я знаю, что я мог бы использовать OR для присоединения, основанный на том, что культура была "fr-FR" или "en-US", но это потенциально удвоило бы количество выбранных строк, и мне потребовалось бы отправить обработанный результирующий набор данных. Я хочу знать, есть ли способ избежать этой пост-обработки.
Недвойственный отказ от ответственности: мой вопрос похож на многие другие, но есть решающее различие. Мне нужно использовать резервное значение для самого условия JOIN, а не как результат запроса. Мое значение по умолчанию не входит в набор данных, но набор данных вычисляется на основе этого значения по умолчанию.
Вы можете присоединиться дважды и использовать COALESCE(), чтобы получить нужное значение:
SELECT p.product_desc,
COALESCE(pLoc_fr.value, pLoc_en.value)
FROM Products p
LEFT OUTER JOIN ProductsLocalization pLoc_us ON
pLoc_us.ProductID = p.ID
AND pLoc_us.Culture = 'en-US'
LEFT OUTER JOIN ProductsLocalization pLoc_fr ON
pLoc_fr.ProductID = p.ID
AND pLoc_fr.Culture = 'fr-FR';
Кроме того, если вы можете представить себе способ комбинирования наборов данных, вы, вероятно, можете достичь использования plain-ol SQL. Некоторым краевым случаям требуется динамически генерировать SQL-запрос, но они не очень распространены. В этом случае вы также можете использовать два коррелированных подзапроса внутри COALESCE или CASE или оператора IF внутри SELECT. Там почти всегда есть несколько способов кожи кошки.