У меня есть следующее SQL заявление в двух версиях. Один использует DECODE другой CASE. Все остальное тоже самое. DECODE работает должным образом, в то время как CASE выдает различный вывод (в основном группы с соответствующими правами доступа). В чем причина?
Оба могут быть запущены на клиенте, без зависимости от схемы БД. Различаются только подзапросы, использующие DECODE или CASE, все остальные части равны.
Любые рекомендации приветствуются!
Выходные DECODE: ![enter image description here](https://i.stack.imgur.com/DZiK6.png)
Выходной CASE: ![enter image description here](https://i.stack.imgur.com/cvB08.png)
DECODE (Short)
...
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
...
CASE Short
...
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
...
DECODE Full
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;
CASE Full
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;