使用GREATEST函数避免NULL返回值

时间:2016-05-30 17:19:26

标签: sql oracle

在使用null参数调用greatest函数时,如何避免null返回值。例如:

select greatest(1,null,2) from dual

以上内容返回null,但我想要2

我不想使用nvl,也不想使用:

coalesce(greatest(term1,term2,term3), greatest(term1,term2), term1).

还有其他方法可以避免null返回值吗?

6 个答案:

答案 0 :(得分:1)

一种解决方案是使用带有公用表表达式的SELECT查询将值放入类似于表的内容中,然后以类似于以下的方式使用SQL MAX函数:

DECLARE
  n1    NUMBER := 1;
  n2    NUMBER := NULL;
  n3    NUMBER := 3;
  nMin  NUMBER := -99999999999999999999999999999999999999e125;
  nMax  NUMBER;
BEGIN
  WITH CTE AS (SELECT n1 AS N FROM DUAL
               UNION ALL
               SELECT n2 AS N FROM DUAL
               UNION ALL
               SELECT n3 AS N FROM DUAL)
  SELECT MAX(COALESCE(n, nMin))
    INTO nMax
    FROM CTE;

  DBMS_OUTPUT.PUT_LINE('nMax=' || nMax);
END;

以上使用COALESCE,它是NVL的ANSI等价物。如果您不想使用NVLCOALESCE,则可以改为使用CASE - 表达式:

  WITH CTE AS (SELECT n1 AS N FROM DUAL
               UNION ALL
               SELECT n2 AS N FROM DUAL
               UNION ALL
               SELECT n3 AS N FROM DUAL)
  SELECT MAX(CASE
               WHEN N IS NULL THEN nMin
               ELSE N
             END)
    INTO nMax
    FROM CTE;

祝你好运。

答案 1 :(得分:1)

如果您使用MAX之类的聚合函数,则会排除NULL个值。但是,您的数据需要以行的形式出现。

WITH mylist AS (
  SELECT NULL AS id FROM DUAL
  UNION
  SELECT 1 FROM DUAL
  UNION
  SELECT 2 FROM DUAL
)
SELECT MAX(id)
  FROM mylist

答案 2 :(得分:1)

好的,不是NVL VALUECOALESCE

CASE
 WHEN term1 IS NULL AND term2 IS NOT NULL AND term3 IS NOT NULL
 THEN GREATEST(term2,term3)

 WHEN term1 IS NOT NULL AND term2 IS NULL AND term3 IS NOT NULL
 THEN GREATEST(term1,term3)

 WHEN term1 IS NOT NULL AND term2 IS NOT NULL AND term3 IS NULL
 THEN GREATEST(term1,term2)

 WHEN term1 IS NOT NULL AND term2 IS NULL AND term3 IS NULL
 THEN term1

 WHEN term1 IS NULL AND term2 IS NOT NULL AND term3 IS NULL
 THEN term2

 WHEN term1 IS NULL AND term2 IS NULL AND term3 IS NOT NULL
 THEN term3

 ELSE GREATEST(term1,term2,term3)
END

但你真的应该COALESCE每个词都有一个适当的低值。

DECLARE MIN_INT CONSTANT := -2147483648;
GREATEST(COALESCE(term1,MIN_INT),COALESCE(term2,MIN_INT),COALESCE(term3,MIN_INT))

答案 3 :(得分:0)

解决方案不是"合并"但评估NVL。如果您事先知道其他两个值是正数,那么您可以执行类似greatest(1, NVL(null, -1), 2)的操作 - 或者更可能的是,如果您有三个数字列,其中任何一个都可以为NULL,并且你知道所有值必须是正数,你可以做greatest(NVL(col1, -1), NVL(col2, -1), NVL(col3, -1))之类的事情 - 然后,如果结果是-1,你会知道所有三个值都是NULL。

但是,如果允许NULL,则可能意味着您有时可能具有未知的值。你的价值观中最大的事实上不可能是这些未知价值之一吗? (也就是说,在这种情况下,greatest()的正确答案是不是NULL?)

增加:您始终可以避免coalesceNVL,例如,而不是NVL(col1, -1)您可以写case when col1 is null then -1 else col1 end - 但为什么???

答案 4 :(得分:0)

Oracle安装程序

CREATE FUNCTION greatest_ignore_null(
  vals SYS.ODCINUMBERLIST
) RETURN NUMBER
IS
  output NUMBER := NULL;
BEGIN
  FOR i IN 1 .. vals.COUNT LOOP
    IF vals(i) IS NOT NULL AND ( output IS NULL OR vals(i) > output ) THEN
      output := vals(i);
    END IF;
  END LOOP;
  RETURN output;
END;
/

<强>查询

SELECT greatest_ignore_null(
         SYS.ODCINUMBERLIST( 1, NULL, 3, NULL, 2 )
       ) AS largest
FROM DUAL;

<强>输出

LARGEST
-------
      3

答案 5 :(得分:0)

根据你的例子尝试这个:

从dual中选择最大值(1,nvl(null,0),2);