如果没有找到行,则为JOIN条件中的后备值

时间:2017-12-13 16:59:12

标签: mysql mariadb

前言:我担心我要求做一些无法实现的事情。但我知道,如果有办法,有人会知道:)

假设我有一个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条件本身使用回退值,而不是查询的结果。我的默认值不会在数据集中结束,但数据集是基于该默认值计算的。

1 个答案:

答案 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语句中的两个相关子查询。几乎总有一些方法可以给猫皮肤。