【问题标题】:Oracle DECODE vs. CASE. Queries return different result setsOracle 解码与案例。查询返回不同的结果集
【发布时间】:2020-03-19 11:18:26
【问题描述】:

我有以下两个版本的 SQL 语句。一个使用 DECODE 另一个 CASE。其他一切都是一样的。 DECODE 按预期工作,而 CASE 提供不同的输出(基本上是具有相应访问权限的组)。是什么原因?

两者都可以在客户端中运行,不依赖于数据库架构。只有使用 DECODE 或 CASE 的子查询不同,其他部分都相同。

欢迎任何建议!

输出解码:

输出案例:

解码(短)

...
SELECT    principal
         || DECODE (MAX (DECODE ("ON", 'N', permission)),
                    NULL, MAX (DECODE ("ON", 'O', permission)),
                    MAX (DECODE ("ON", 'N', permission)))    latest_permission,
            principal
         || DECODE (MAX (DECODE ("ON", 'O', permission)),
                    NULL, MAX (DECODE ("ON", 'N', permission)),
                    MAX (DECODE ("ON", 'O', permission)))    dont_overwrite_existing
    FROM
...

案例短


...
SELECT    principal
     || CASE MAX (
                 CASE "ON" WHEN 'N' THEN permission END)
            WHEN NULL
            THEN
                MAX (
                    CASE "ON"
                        WHEN 'O' THEN permission
                    END)
            ELSE
                MAX (
                    CASE "ON"
                        WHEN 'N' THEN permission
                    END)
        END    latest_permission,
        principal
     || CASE MAX (
                 CASE "ON" WHEN 'O' THEN permission END)
            WHEN NULL
            THEN
                MAX (
                    CASE "ON"
                        WHEN 'N' THEN permission
                    END)
            ELSE
                MAX (
                    CASE "ON"
                        WHEN 'O' THEN permission
                    END)
        END    dont_overwrite_existing

FROM 
...

完整解码


WITH
    old
    AS
        (SELECT REGEXP_SUBSTR (acl, '[^\(]+')     principal,
                REGEXP_SUBSTR (acl, '\(.+')       permission
           FROM (    SELECT REGEXP_SUBSTR (
                                ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)',
                                '[^,]+',
                                1,
                                LEVEL)    acl
                       FROM DUAL
                      WHERE ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)'
                                IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (
                                ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)',
                                '[^,]+',
                                1,
                                LEVEL)
                                IS NOT NULL)),
    new
    AS
        (SELECT REGEXP_SUBSTR (acl, '[^\(]+')     principal,
                REGEXP_SUBSTR (acl, '\(.+')       permission
           FROM (    SELECT REGEXP_SUBSTR (':Group1(R),:Group1(RW),:GroupA(RWDA),:Group5(R)',
                                           '[^,]+',
                                           1,
                                           LEVEL)    acl
                       FROM DUAL
                      WHERE ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4(R)'
                                IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (
                                ':Group1(R),:Group1(RW),:GroupA(RWDA),:Group5(R)',
                                '[^,]+',
                                1,
                                LEVEL)
                                IS NOT NULL)),
    principalsToDelete
    AS
        (SELECT DISTINCT REGEXP_SUBSTR (acl, '[^\(]+')     principal
           FROM (    SELECT REGEXP_SUBSTR (NULL,
                                           '[^,]+',
                                           1,
                                           LEVEL)    acl
                       FROM DUAL
                      WHERE NULL IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (NULL,
                                           '[^,]+',
                                           1,
                                           LEVEL)
                                IS NOT NULL))
  SELECT    principal
         || DECODE (MAX (DECODE ("ON", 'N', permission)),
                    NULL, MAX (DECODE ("ON", 'O', permission)),
                    MAX (DECODE ("ON", 'N', permission)))    latest_permission,
            principal
         || DECODE (MAX (DECODE ("ON", 'O', permission)),
                    NULL, MAX (DECODE ("ON", 'N', permission)),
                    MAX (DECODE ("ON", 'O', permission)))    dont_overwrite_existing
    FROM (SELECT o.*, 'O' "ON"
            FROM old o
          UNION
          SELECT n.*, 'N' "ON"
            FROM new n)
   WHERE principal NOT IN (SELECT principal FROM principalsToDelete)
GROUP BY principal
ORDER BY principal;

案例完整


WITH
    old
    AS
        (SELECT REGEXP_SUBSTR (acl, '[^\(]+')     principal,
                REGEXP_SUBSTR (acl, '\(.+')       permission
           FROM (    SELECT REGEXP_SUBSTR (
                                ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)',
                                '[^,]+',
                                1,
                                LEVEL)    acl
                       FROM DUAL
                      WHERE ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)'
                                IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (
                                ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4((R)',
                                '[^,]+',
                                1,
                                LEVEL)
                                IS NOT NULL)),
    new
    AS
        (SELECT REGEXP_SUBSTR (acl, '[^\(]+')     principal,
                REGEXP_SUBSTR (acl, '\(.+')       permission
           FROM (    SELECT REGEXP_SUBSTR (':Group1(R),:Group1(RW),:GroupA(RWDA),:Group5(R)',
                                           '[^,]+',
                                           1,
                                           LEVEL)    acl
                       FROM DUAL
                      WHERE ':Group1(RWDA),:Group2(RWD),:Group3(RW),:Group4(R)'
                                IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (
                                ':Group1(R),:Group1(RW),:GroupA(RWDA),:Group5(R)',
                                '[^,]+',
                                1,
                                LEVEL)
                                IS NOT NULL)),
    principalsToDelete
    AS
        (SELECT DISTINCT REGEXP_SUBSTR (acl, '[^\(]+')     principal
           FROM (    SELECT REGEXP_SUBSTR (NULL,
                                           '[^,]+',
                                           1,
                                           LEVEL)    acl
                       FROM DUAL
                      WHERE NULL IS NOT NULL
                 CONNECT BY REGEXP_SUBSTR (NULL,
                                           '[^,]+',
                                           1,
                                           LEVEL)
                                IS NOT NULL))
  SELECT    principal
         || CASE MAX (
                     CASE "ON" WHEN 'N' THEN permission END)
                WHEN NULL
                THEN
                    MAX (
                        CASE "ON"
                            WHEN 'O' THEN permission
                        END)
                ELSE
                    MAX (
                        CASE "ON"
                            WHEN 'N' THEN permission
                        END)
            END    latest_permission,
            principal
         || CASE MAX (
                     CASE "ON" WHEN 'O' THEN permission END)
                WHEN NULL
                THEN
                    MAX (
                        CASE "ON"
                            WHEN 'N' THEN permission
                        END)
                ELSE
                    MAX (
                        CASE "ON"
                            WHEN 'O' THEN permission
                        END)
            END    dont_overwrite_existing

    FROM (SELECT o.*, 'O' "ON"
            FROM old o
          UNION
          SELECT n.*, 'N' "ON"
            FROM new n)
   WHERE principal NOT IN (SELECT principal FROM principalsToDelete)
GROUP BY principal
ORDER BY principal;

【问题讨论】:

  • 。 .您应该真正简化问题,只关注不同的代码。这也有助于了解不同的结果。
  • 正确!更新了!

标签: sql oracle case decode


【解决方案1】:

差异来自与null比较时的行为差异:

SQL> select decode(null,null,1) from dual;

DECODE(NULL,NULL,1)
-------------------
                  1

SQL> select case null when null then 1 end from dual;

CASENULLWHENNULLTHEN1END
------------------------

第二个查询返回 NULL 而不是 1,因此当 x 为 NULL 时,'case x when null then 1 end' 不会返回 1,而这可行:

SQL> select case when null is null then 1 end from dual;

CASEWHENNULLISNULLTHEN1END
--------------------------
                         1

【讨论】:

  • 您的解决方案确实有效。我不知道 case 表达式实际上可以保持为空。这不是滥用 CASE 子句吗?如果我需要检查多个值,就像我的情况一样,那么我将不得不在每个 WHEN 语句中进行比较,而不是只将一个值与 CASE 表达式进行比较,该表达式现在是空的。对吗?
  • 您必须在 null then... 时更改 case x,但您可以将 'case x when 'O' then ...' 保持原样。事实上,在 SQL 中,这两个谓词不是同一个 'x is null' 和 'x=null'。
  • 这很清楚。 CASE 可以在内部处理差异。无论如何,谢谢你的回答
猜你喜欢
  • 2014-12-25
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-08
  • 2011-10-25
  • 1970-01-01
相关资源
最近更新 更多