将嵌套解码转换为等效的 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 类

将 SQL CASE WHEN 语句转换为 C#

在Ruby中将嵌套哈希键从CamelCase转换为snake_case

嵌套 case 中的 case 语句

PYSPARK:如何将带有多个 case 语句的 SQL 查询转换为 Pyspark/Pyspark-SQL?