Oracle INNER JOIN ON CASE WHEN 条件

Oracle INNER JOIN ON CASE WHEN condition

我有两个子查询需要(内部)加入一个列(“id”)。不幸的是,我加入的一些值之前已经在某处更改过,因此 INNER JOINON 条件应该根据另一列的值有条件地从两个中选择(“鉴别器”)。一个简化的例子如下:

示例结果集查询 1 (q1)

ID       DATA                DISCRIMINATOR
==========================================
1 1      Whatever            NULL
2AB      NULL                yes
4f-G     Could be anything   no
2CD      This one not        yes
2EEF     But this one        yes
11       And this            no
211      Last one            no

示例结果集查询 2 (q2)

ID       OTHERDATA     
====================
1 1      foo          
A B      bar               
EE F     foobar
G HH     barfoo
11       foofoo

如果鉴别器为“是”,则通过在前面加上“2”并删除所有空格来更改 q1 中的 ID,否则,它们是相同的。我仍然希望能够正确地连接表,并在连接中保留来自 q2 的 ID。

预期示例结果

ID       DATA                OTHERDATA
==========================================
1 1      Whatever            foo
11       And this            foofoo
A B      NULL                bar
EE F     But this one        foobar

我能以某种方式在 ON 条件下执行 CASE WHEN 吗?我尝试了以下

SELECT q2.id
    , q1.data
    , q2.otherdata
FROM ((...somequery...) q1
      INNER JOIN
      (...somequery...) q2
      ON CASE WHEN discriminator = 'yes' THEN TRIM(q1.id) = CONCAT('2', REPLACE(RTRIM(q2.id), ' ', ''))
          ELSE q1.id = q2.id
      END
     )
ORDER BY id
;

但我收到 missing keyword 错误。我摆弄了一下,但仍然无法在 ON 条件下正确使用 CASE WHEN

我知道我可以使用 UNION 来做一些类似

的事情
SELECT q2.id
    , q1.data
    , q2.otherdata
FROM ((...somequery...) q1 INNER JOIN (...somequery...) q2 
           ON q1.id = q2.id
               AND (discriminator <> 'yes' OR discriminator IS NULL)
         )
UNION
SELECT q2.id
    , q1.data
    , q2.otherdata
FROM ((...somequery...) q1 INNER JOIN (...somequery...) q2 
           ON TRIM(q1.id) = CONCAT('2', REPLACE(RTRIM(q2.id), ' ', ''))
               AND discriminator = 'yes'
          )
ORDER BY id
;

但这需要执行两次子查询,不是吗?我宁愿找到一种避免这种情况的方法。

是否可以在 INNER JOIN 子句中以有条件地使用两个 ON 条件之一的方式使用 CASE WHEN 语句?还是有其他优雅的方式?

是的,有可能:

SELECT q2.id
    , q1.data
    , q2.otherdata
FROM ((...somequery...) q1
      INNER JOIN
      (...somequery...) q2
      ON (CASE WHEN discriminator = 'yes' AND TRIM(q1.id) = CONCAT('2', REPLACE(RTRIM(q2.id), ' ', '')) THEN 1
             WHEN (discriminator <> 'yes' OR discriminator IS NULL) AND q1.id = q2.id THEN 1
      END) = 1
     )
ORDER BY id
;