Oracle INNER JOIN ON CASE WHEN 条件
Oracle INNER JOIN ON CASE WHEN condition
我有两个子查询需要(内部)加入一个列(“id”)。不幸的是,我加入的一些值之前已经在某处更改过,因此 INNER JOIN
的 ON
条件应该根据另一列的值有条件地从两个中选择(“鉴别器”)。一个简化的例子如下:
示例结果集查询 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
;
我有两个子查询需要(内部)加入一个列(“id”)。不幸的是,我加入的一些值之前已经在某处更改过,因此 INNER JOIN
的 ON
条件应该根据另一列的值有条件地从两个中选择(“鉴别器”)。一个简化的例子如下:
示例结果集查询 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
;