oracle: декодирование и подзапрос выбрать результат

у меня есть запрос oracle, и часть его вычисляет некоторое значение с помощью DECODE. Например:

SELECT ..., 
      (SELECT DECODE((SELECT 23 FROM DUAL), 
                      0, null,
                     (SELECT 23 FROM DUAL))  
         FROM DUAL) 
  FROM ...

здесь значение " 23 " вычисляется во время выполнения, и это довольно сложные соединения - несколько таблиц, использует PARTITION BY etc. Поэтому я хочу избежать выполнения того же подзапроса, если значение не "0". Есть ли способ написать что-то подобное

SELECT ..., 
       (SELECT DECODE ((SELECT 23 FROM DUAL) as test, 
                        0, null,
                       test)  
         FROM DUAL) 
  FROM ...

5 ответов


это будет работать для вас? Я только что переместил " 23 " в встроенную таблицу с описательным псевдонимом.

select ..., 
  (
   select 
     decode ( 
            computed_value.val, 
            0, null,
            computed_value.val
            )  
   from
     (select 23 as val from dual) computed_value
  )
from
  ...

оператор CASE также может добавить ясности, как в:

select
  ...
 ,case when computed_value.val = 0
       then null
       else computed_value.val
       end as my_field
from
  (select 23 as val from dual) computed_value
  ...

или:

WITH q AS (
SELECT 23 test, 16 test2 FROM dual
)
SELECT ... 
     , DECODE(q.test, 0, NULL, q.test) value
     , CASE WHEN q.test2 = 0 THEN NULL 
            WHEN q.test2 = 16 THEN 1
            ELSE q.test2
       END another_value
  FROM q, ...

позволяет использовать запрос " q " во всем главном выборе, где когда-либо разрешен подзапрос. Вызывается предложение WITH, или общее табличное выражение, или Факторинг подзапросов. Подробнее об этом читайте вOracle-Base.com.


для этого конкретного сценария вы можете использовать NULLIF функция:

SELECT ..., 
      (SELECT NULLIF((SELECT 23 FROM DUAL), 0)  
         FROM DUAL) 
  FROM ...

на NULLIF возвращает функция NULL если два аргумента равны, в противном случае она возвращает первый аргумент.


вы можете использовать подзапрос в предложении from и сделать что-то вроде ниже:

select conf_key, decode(test, 0, null, test) from (
select conf_key, (select conf_value from config_values where conf_key = 'DOMAINID') as TEST from config_values )

лучше бы у вас был оператор use CASE. поскольку оператор CASE похож на серию операторов IF, используйте только ключевое слово WHEN. Оператор CASE оценивается сверху вниз. Если условие истинно, то выполняется соответствующее предложение THEN и выполнение переходит к предложению END CASE (оценка короткого замыкания).