【问题标题】:Find distinct rows in Mysql by using conditions使用条件在 Mysql 中查找不同的行
【发布时间】:2021-04-14 16:56:38
【问题描述】:

标题含糊,抱歉。

我正在尝试将客户端代码转换为 Mysql 5.7 中的“纯”sql(如果有任何区别 - 解决方案也只能适用于 MariaDB 10.1)。

我有一个“codes”表和“code_translations”表。我现在正在尝试为代码表中的每个代码输出“最佳可用翻译”。

如果有要求给我代码“A”和翻译语言“de”的翻译 - 尝试首先找到带有“de”的翻译。如果未找到 - 使用“en”的可用翻译(默认后备)。如果没有“en” - 取由当前排序确定的第一个可用翻译。

从小提琴:

CREATE TABLE codes (id SERIAL, code TEXT, country TEXT);
CREATE TABLE code_translations (id SERIAL, code_id INT, language TEXT, label TEXT);

INSERT INTO codes (id, code, country) 
VALUES 
    (1, 'A', 'DE'),  
    (2, 'B', 'DE'),
    (3, 'C', 'DE');

INSERT INTO code_translations (code_id, language, label) 
VALUES
    (1, 'de', 'A-de'),
    (1, 'en', 'A-en'),
    (1, 'fr', 'A-fr'),
    (2, 'de', 'B-de'),
    (2, 'en', 'B-en'),
    (3, 'nl', 'C-nl'),
    (3, 'ru', 'C-ru');

基本选择 - 只产生所有行:

SELECT c.code,ct.label
FROM codes c
JOIN code_translations ct ON c.id=ct.code_id
-- WHERE ct.language=de
-- WHERE ct.language=fr
-- WHERE ct.language=ru

期望的输出:

-- WHERE language = de
-- output should be
-- |A|A-de| -- de is the direct match
-- |B|B-de| -- de is the direct match
-- |C|C-nl| -- first match determined by ordering

-- WHERE language = fr
-- output should be
-- |A|A-fr| -- fr is the direct match
-- |B|B-en| -- no "fr" - take "en"
-- |C|C-nl| -- first match determined by ordering

-- WHERE language = ru
-- output should be
-- |A|A-en| -- no "ru" - take "en"
-- |B|B-en| -- no "ru" - take "en"
-- |C|C-ru| -- ru is the direct match

【问题讨论】:

    标签: mysql sql mariadb


    【解决方案1】:

    使用相关子查询为每个codecode_translations 的行进行排序,使得第一行是查询的语言(如果存在)或默认的后备语言(如果存在),或其他语言。
    这种排序可以通过函数FIELD()来完成。
    最后使用LIMIT 1 只获取第一行:

    SELECT c.code,
           (
             SELECT ct.label
             FROM code_translations ct
             WHERE ct.code_id = c.id
             ORDER BY FIELD(ct.language, ?2, ?1) DESC
             LIMIT 1
           ) label
    FROM codes c
    

    ?1 替换为查询语言,将?2 替换为备用语言。

    请参阅demo

    【讨论】:

      【解决方案2】:

      您可以使用相关子查询来获取每个代码的语言。您可以先获得所需的语言,然后是英语。但是,如果这些不可用,则没有“第一”语言——因为 SQL 表代表 无序 集。您可以使用 任意 语言:

      select c.*, ct.language, ct.label
      from (select c.*,
                   (select ct.language
                    from code_translations ct
                    where ct.code_id = c.id
                    order by ct.language = 'de' desc,
                             ct.language = 'en' desc
                    limit 1
                   ) as language
            from codes c
           ) c left join
           code_translations ct
           on ct.code_id = c.id and ct.language = c.language;
      

      如果您有一个定义“第一”语言的顺序,您可以将其作为第三个键包含在 order by 中。

      Here 是一个 dbfiddle。

      【讨论】:

        猜你喜欢
        • 2021-09-02
        • 1970-01-01
        • 2023-03-19
        • 2011-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多