前言:我担心我要求做一些无法实现的事情。但我知道,如果有办法,有人会知道:)
假设我有一个MySQL数据库(或者一个MariaDB,如果可以保留兼容性)。我需要从TableA中选择并基于某个具有特定值X的列连接TableB;表B中可能没有合适的行,这意味着我将使用LEFT OUTER JOIN。但是,如果没有找到行(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条件本身使用回退值,而不是查询的结果。我的默认值不会在数据集中结束,但数据集是基于该默认值计算的。
答案 0 :(得分:1)
您可以加入两次并使用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';
另外,如果你能想象一种组合数据集的方法,你可以使用普通的SQL来实现。一些边缘情况需要动态生成SQL语句,但这些并不是非常常见。在这种情况下,您还可以在SELECT内部使用COALESCE或CASE或IF语句中的两个相关子查询。几乎总有一些方法可以给猫皮肤。