Oracle SQL 条件连接

Posted

技术标签:

【中文标题】Oracle SQL 条件连接【英文标题】:Oracle SQL conditional join 【发布时间】:2016-04-25 18:07:54 【问题描述】:

我有以下 SQL 语句:

select
    DOCUMENT.DOCUMENT_ID,
    (case
        when DOCUMENT.CLASSIFICATION_CODE is not null
        then DOCUMENT.CLASSIFICATION_CODE
        else TEMPLATE.CLASSIFICATION_CODE end) CLASSIFICATION_CODE,
    CLASSIFICATION.NAME CLASSIFICATION_NAME
from
    DOCUMENT,
    TEMPLATE,
    CLASSIFICATION
where
    DOCUMENT.TEMPLATE_ID = TEMPLATE.TEMPLATE_ID and
    DOCUMENT.CLASSIFICATION_CODE = CLASSIFICATION.CLASSIFICATION_CODE(+)

我想做的是:

if DOCUMENT.CLASSIFICATION_CODE IS NOT NULL THEN 
  DOCUMENT.CLASSIFICATION_CODE = CLASSIFICATION.CLASSIFICATION_CODE(+),
ELSE
  TEMPLATE.CLASSIFICATION_CODE = CLASSIFICATION.CLASSIFICATION_CODE(+)

这可能吗?

【问题讨论】:

学习使用正确的显式JOIN 语法。谁能记住(+)WHERE 子句中的含义? 哎呀!非ANSI外连接语法? 2016年!?!?!这个世界会变成什么样子! 【参考方案1】:

您可以为此使用NVL 或更标准的COALESCE:

COALESCE(DOCUMENT.CLASSIFICATION_CODE, TEMPLATE.CLASSIFICATION_CODE)
      = CLASSIFICATION.CLASSIFICATION_CODE(+)

ANSI 语法:

select
    DOCUMENT.DOCUMENT_ID,
    COALESCE(DOCUMENT.CLASSIFICATION_CODE, TEMPLATE.CLASSIFICATION_CODE) 
        CLASSIFICATION_CODE,
    CLASSIFICATION.NAME CLASSIFICATION_NAME
from
    DOCUMENT
inner join 
    TEMPLATE on DOCUMENT.TEMPLATE_ID = TEMPLATE.TEMPLATE_ID
left join
    CLASSIFICATION on
         COALESCE(DOCUMENT.CLASSIFICATION_CODE, TEMPLATE.CLASSIFICATION_CODE) 
       = CLASSIFICATION.CLASSIFICATION_CODE

【讨论】:

【参考方案2】:

虽然您可以使用coalescenvl,但正如其他答案所建议的那样,我更愿意加入classification 表两次。是的,引擎必须执行额外的连接,但避免这些函数允许引擎使用索引。

SELECT document.document_id,
       COALESCE (d.classification_code, t.classification_code)
          AS classification_code,
       COALESCE (d_c.name, t_c.name) AS classification_name
FROM   document d
       JOIN template t ON d.template_id = t.template_id
       LEFT JOIN classification d_c
          ON d.classification_code = d_c.classification_code
       LEFT JOIN classification t_c
          ON t.classification_code = t_c.classification_code

【讨论】:

【参考方案3】:

你可以使用:

NVL( DOCUMENT.CLASSIFICATION_CODE, TEMPLATE.CLASSIFICATION_CODE ) COALESCE( DOCUMENT.CLASSIFICATION_CODE, TEMPLATE.CLASSIFICATION_CODE )CASE WHEN DOCUMENT.CLASSIFICATION_CODE IS NOT NULL THEN DOCUMENT.CLASSIFICATION_CODE ELSE TEMPLATE.CLASSIFICATION_CODE END(与您在SELECT 子句中使用的完全相同)

作为连接条件,像这样:

SELECT d.DOCUMENT_ID,
       NVL( d.CLASSIFICATION_CODE, t.CLASSIFICATION_CODE )
         AS CLASSIFICATION_CODE,
       c.NAME AS CLASSIFICATION_NAME
FROM   DOCUMENT d
       INNER JOIN TEMPLATE t
       ON ( d.TEMPLATE_ID = t.TEMPLATE_ID )
       LEFT OUTER JOIN CLASSIFICATION c
       ON ( NVL( d.CLASSIFICATION_CODE, t.CLASSIFICATION_CODE )
              = c.CLASSIFICATION_CODE )

【讨论】:

以上是关于Oracle SQL 条件连接的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL 在 2 个条件下连接列

根据条件更改连接条件 - Oracle

Oracle优化器的基础知识

sql 各种连接的使用条件,

oracle 嵌套查询 子查询 自连接 等值连接条件

Oracle SQL - 基于 concat 的外连接