将嵌套解码转换为等效的 CASE 语句(需要从 Oracle 转换为 PostgreSQL)
Posted
技术标签:
【中文标题】将嵌套解码转换为等效的 CASE 语句(需要从 Oracle 转换为 PostgreSQL)【英文标题】:Converting a nested decode into equivalent CASE statement (needed for conversion from Oracle to PostgreSQL) 【发布时间】:2018-09-04 11:52:47 【问题描述】:我使用的是 Oracle 11.2.0.4。我有一个嵌套的 DECODE 语句,我需要将其转换为 CASE 语句。有人可以帮忙吗。我不确定它是如何完成的,事实上我并不完全理解它的逻辑。如果有人可以解释它基本上打算做什么以及使用对我非常有用的 CASE 重写的功能是什么。这里是函数......(注意:不要担心表连接,有3个表和一个条件等。请关注DECODE及其转换为CASE)。此外,我必须手动转换,工具不是一种选择。
CREATE OR REPLACE FUNCTION TMP_Func
RETURN NUMBER
IS
V NUMBER;
BEGIN
SELECT DECODE (
NVL (tab1.flag1, '~'),
'D', DECODE (tab1.code_oid, NVL (tab3.bu_id, '-'), 1, 0),
'C', DECODE (tab1.code_oid, NVL (tab3.cost_id, '-'), 1, 0),
DECODE (tab2.oid,
DECODE (tab1.co_id, NULL, tab2.oid, tab1.co_id), 1,
0))
INTO V
FROM tab1, tab2, tab3
WHERE tab2.OID = tab1.sec_id;
RETURN V;
END;
【问题讨论】:
【参考方案1】:应该是这样的:
SELECT CASE
WHEN NVL (tab1.flag1, '~') = 'D'
THEN
CASE
WHEN tab1.code_oid = NVL (tab3.bu_id, '-') THEN 1
ELSE 0
END
WHEN NVL (tab1.flag1, '~') = 'C'
THEN
CASE
WHEN tab1.code_oid = NVL (tab3.cost_id, '-') THEN 1
ELSE 0
END
ELSE
CASE
WHEN tab2.oid =
CASE
WHEN tab1.co_id IS NULL THEN tab2.oid
ELSE tab1.co_id
END
THEN
1
ELSE
0
END
END
INTO v
FROM ...
请注意,您的 FROM
子句包含 3 个表,但 WHERE
仅连接其中两个。 tab3
呢?另外,考虑切换到 ANSI 连接。
【讨论】:
非常感谢。这对我最有用。【参考方案2】:类似这样的:
select CASE WHEN COALESCE(tab1.flag1,'~') = 'D' THEN
CASE WHEN tab1.code_oid=COALESCE(tab3.bu_id, '-') THEN 1 else 0 end
WHEN COALESCE(tab1.flag1,'~')='C' THEN
CASE WHEN tab1.code_oid=COALESCE(tab3.cost_id, '-') THEN 1 else 0 end
else
CASE WHEN tab2.oid=COALESCE(tab1.co_id,tab2.oid) THEN 1 else 0 end
end
FROM tab1, tab2, tab3
WHERE tab2.OID = tab1.sec_id;
NVL 被 COALESCE 取代
DECODE(a,b,c,d,e,...,f) 被替换为:
CASE WHEN a=b THEN c
WHEN a=d THEN e
...
else f
end
您的最后一次解码( DECODE (tab1.co_id, NULL, tab2.oid, tab1.co_id), 1, 0))) 实际上是一个 NVL(tab1.co_id,tab2.oid)
【讨论】:
我猜两个答案不能被接受 - 只是为了澄清我认为包括这个答案在内的两个答案都绝对适合我,但我不能在网站上标记两个答案。但是非常感谢!【参考方案3】:以下应该做你想做的事:
SELECT CASE COALESCE(TAB1.FLAG1, '~')
WHEN 'D' THEN CASE
WHEN TAB1.CODE_OID = COALESCE(TAB3.BU_ID, '-') THEN 1
ELSE 0
END
WHEN 'C' THEN CASE
WHEN TAB1.CODE_OID = COALESCE(TAB3.COST_ID, '~') THEN 1
ELSE 0
END
ELSE CASE
WHEN TAB2.OID = COALESCE(TAB1.CO_ID, TAB2.OID) THEN 1
ELSE 0
END
END
INTO V
FROM TAB1
INNER JOIN TAB2
ON TAB2.OID = TAB2.SEC_ID
CROSS JOIN TAB3;
请注意,NVL 和 COALESCE 在几个方面略有不同,尽管这两者似乎都不是一个因素。首先,NVL 总是接受两个参数,而 COALESCE 可以接受尽可能多的参数——它返回第一个非 NULL 参数。其次,NVL 总是评估它的两个参数(例如,如果为 NVL 的一个或两个参数指定了一个函数,两个函数都会被调用),而 COALESCE 只评估尽可能多的参数是必要的查找非 NULL 结果;因此,如果给 COALESCE 两个函数作为参数并且第一个返回非 NULL 值,则永远不会调用第二个函数。这里不是问题,但在其他情况下可能很重要(由于副作用)。
祝你好运。
【讨论】:
非常感谢鲍勃!以上是关于将嵌套解码转换为等效的 CASE 语句(需要从 Oracle 转换为 PostgreSQL)的主要内容,如果未能解决你的问题,请参考以下文章
case/switch 语句的 Python 等效项是啥? [复制]
无法使用 Gson 将包含嵌套 json 数组的 json 转换为等效的 JAVA 类