【问题标题】:LEFT JOIN using OR使用 OR 左连接
【发布时间】:2010-11-16 17:35:32
【问题描述】:

我想知道如果两者都评估为true,我将如何返回OR 中使用的OR 子句中最左边的条件的结果@。

到目前为止,我遇到的解决方案都涉及在SELECT 中使用CASE 语句,这确实意味着我会放弃OR 子句。

另一个解决方案涉及在ORDER BY 中使用CASE 语句。

是否有任何其他解决方案可以减少 CASE 语句的使用。我问的原因是因为现在只有两个LEFT JOINs,但随着时间的推移会添加更多。

SELECT item.id,
       item.part_number,
       lang.data AS name,
       lang2.data AS description
  FROM item
       LEFT JOIN
       language lang
          ON     item.id = lang.item
             AND (lang.language = 'fr' OR lang.language = 'en')
       LEFT JOIN
       language lang2
          ON     item.id = lang2.item
             AND (lang2.language = 'fr' OR lang2.language = 'en')
 WHERE item.part_number = '34KM003KL'

【问题讨论】:

  • 我不明白您的查询... lang.data 和 lang2.data 将始终返回相同的内容。
  • 你为什么要以相同的加入条件加入 Language 两次?
  • 抱歉,我的示例语句中没有包含“lang.type”。它应该是 lang.type = 'NAME' 和 lang2.type = 'DESCRIPTION'
  • @Martin L:正如所写,lang.data 和 lang2.data 不会总是返回相同的东西。如果 Lang 中有 Nrows 满足条件,N>1,那么您将在查询中返回 N^2 行,Lang 和 Lang2 是不同的 Language 行,在除 N 个案例之外的所有案例中都满足条件。
  • @Andre,您声明需要额外的左连接。你的意思是除了NAME和DESCRIPTION之外还会定义额外的Language.Type?还是您的意思是 Language.language 将被扩展以包含更多的 'fr' 和 'en'?

标签: sql join default-value


【解决方案1】:

你为什么不在 WHERE 子句中做你的标准?

SELECT item.id, item.part_number, lang.data AS name, lang2.data AS description 
    FROM item AS item
    LEFT JOIN language AS lang ON item.id = lang.item 
    LEFT JOIN language AS lang2 ON item.id = lang2.item 
    WHERE item.part_number = '34KM003KL'
        AND (lang.language = 'fr' OR lang.language = 'en')
        AND (lang2.language = 'fr' OR lang2.language = 'en')

【讨论】:

    【解决方案2】:

    如果存在,您似乎想要法语描述,否则回退到英语。

    SELECT  item.id,
            COALESCE(
            (
            SELECT  lang.data
            FROM    language l
            WHERE   l.item = i.id
                    AND l.language = 'fr'
            ),
            (
            SELECT  lang.data
            FROM    language l
            WHERE   l.item = i.id
                    AND l.language = 'en'
            )
            ) AS description
    FROM    item i
    

    ,或者这个:

    SELECT  item.id,
            COALESCE(lfr.data, len.data)
    FROM    item i
    LEFT JOIN
            language lfr
    ON      lfr.item = i.id
            AND lfr.language = 'fr'
    LEFT JOIN
            language len
    ON      len.item = i.id
            AND len.language = 'en'
    

    如果找到法语描述的概率很高,则第一个查询效率更高(如果第一个成功,它将不会评估第二个子查询)。

    SQL ServerOraclePostgreSQL 中,如果你有很多法语描述,这个可能会更有效:

    SELECT  item.id,
            COALESCE(
            lfr.data,
            (
            SELECT  lang.data
            FROM    language l
            WHERE   l.item = i.id
                    AND l.language = 'en'
            )
            ) AS description
    FROM    item i
    LEFT JOIN
            language lfr
    ON      lfr.item = i.id
            AND lfr.language = 'fr'
    

    此查询将使用一种有效的方法(HASH JOINMERGE JOIN)加入法语描述,并且仅在必要时回退到英语。

    对于 MySQL1st3rd 查询没有区别。

    在所有系统中,在language (item, language)上创建一个复合索引

    【讨论】:

      【解决方案3】:

      如果您想要法语翻译(如果存在)和英语作为二手选择,您可以为每种语言加入一次语言表:

      select
         item.id, item.part_number, isnull(fr.data, en.data) as name
      from
         item
         left join language fr on fr.item = item.id and fr.language = 'fr'
         left join language en on en.item = item.id and en.language = 'en'
      where
         item.part_number = '34KM003KL'
      

      【讨论】:

        【解决方案4】:

        也许你想要这样的东西:

        SELECT item.id, item.part_number, COALESCE (lang.data, lang2.data) AS description 
        FROM item AS item
        LEFT JOIN language AS lang ON item.id = lang.item AND lang.language = 'fr'
        LEFT JOIN language AS lang2 ON item.id = lang2.item AND lang2.language = 'en'
        WHERE item.part_number = '34KM003KL'
        

        如果法语和英语都存在,或者只有法语存在,则返回法语数据。

        【讨论】:

          【解决方案5】:

          您可以将多个 Ors 更改为使用 In 子句...

          SELECT i.id, i.part_number, L1.data name, L2.data description 
          FROM item i
             LEFT JOIN language L1 ON i.id = L1.item 
                AND L1.language In ('fr', 'en')
             LEFT JOIN language L2 ON i.id = L2.item 
                AND L2.language In ('fr', 'en')
          WHERE i.part_number = '34KM003KL'
          

          【讨论】:

          • 您可能还可以从 udf 返回列表 ('fr', 'en') 以便以后扩展。
          • 如果const 以文字形式提供,则所有主要的RDBMS 都会为ID = IN (const1, const2)ID = const1 OR ID = const2 生成相同的计划。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-23
          • 2021-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-14
          • 2021-06-08
          相关资源
          最近更新 更多