如果未找到行,JOIN 条件中的回退值

Sim*_*one 4 mysql mariadb

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

假设我有一个 MySQL 数据库(或者 MariaDB 数据库,如果可以保留兼容性)。我需要根据具有特定值X的特定列从TableA中选择并连接TableB;TableB 中可能不存在合适的行,这意味着我将使用 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'
Run Code Online (Sandbox Code Playgroud)

当没有可用的法语信息时,我将得到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'
Run Code Online (Sandbox Code Playgroud)

但后一个查询当然是不可接受的。

我知道我可以根据文化为“fr-FR”“en-US”使用 OR 进行连接,但这可能会使所选行的数量增加一倍,并且需要我对生成的数据集进行后处理。我想知道是否有办法避免这种后处理。

非重复免责声明:我的问题与许多其他问题类似,但有一个至关重要的区别。我需要为 JOIN 条件本身使用后备值,而不是作为查询的结果。我的默认值不会出现在数据集中,但数据集是根据该默认值计算的。

JNe*_*ill 6

您可以加入两次并使用 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';
Run Code Online (Sandbox Code Playgroud)

另外,如果您可以想象一种组合数据集的方法,您可能可以使用普通 SQL 来实现。某些边缘情况需要动态生成 SQL 语句,但这些情况并不常见。在这种情况下,您还可以在 SELECT 内的 COALESCE 或 CASE 或 IF 语句内使用两个相关子查询。剥猫皮几乎总是有几种方法。