Oracle SQL 中最小值但不为 NULL

问题描述 投票:0回答:8

我想在我的程序中使用函数 LEAST 来找到最小值。问题是有些值可能是 NULL,所以如果我这样做

select least(NULL,0,1) from dual

我得到的答案是 NULL,这可能是正确的,因为这不是我期望返回的东西。我想获得最小的真实非零值。非常感谢任何帮助。

sql oracle-database
8个回答
22
投票

如果任何参数为 NULL,则您希望采用其他参数中的最少值。如果所有参数均为 NULL,您希望返回 NULL。

我可能会用这样的东西来表示两个参数:

LEAST(NVL(colA,colB), NVL(colB,colA))

对于>2个参数,它开始变得丑陋:

LEAST(COALESCE(colA,colB,colC)
     ,COALESCE(colB,colA,colC)
     ,COALESCE(colC,colA,colB))

此时我会开始考虑魔法值;但这可能有问题(例如,如果其中一个值合法地魔法值怎么办?):

SELECT CASE WHEN r = maxv THEN NULL ELSE r END AS result
FROM   (SELECT LEAST(NVL(:colA,maxv)
                    ,NVL(:colB,maxv)
                    ,NVL(:colC,maxv)) AS r, maxv
        FROM   (SELECT 9.999999999999999999999999999999999999999e125
                       AS maxv FROM DUAL));

5
投票

我怀疑这实际上是您的查询。也许你正在做类似这样的事情?

select least(some_column) from dual

如果是这样,请将其更改为:

select least(some_column) from dual where some_column is not null

或者,如果你正在做类似这样的事情,你不能只使用

where
来过滤集合,

select least(expr1,expr2,expr3) from dual

这样做:

select least(coalesce(expr1, 12345), coalesce(expr2, 12345), coalesce(expr3, 12345)) from dual

其中

12345
是一个足够大的值,只有当所有其他表达式都是
NULL
时才会选择它。


3
投票

从第 1 列到第 N 列的最低值:

SELECT
    LEAST(COALESCE(Col1, BINARY_DOUBLE_INFINITY),
          COALESCE(Col2, BINARY_DOUBLE_INFINITY),
          ... ,
          COALESCE(ColN, BINARY_DOUBLE_INFINITY)
    )
FROM MY_TABLE

从第 1 列到第 N 列的最大值:

SELECT
    GREATEST(
        COALESCE(Col1, -BINARY_DOUBLE_INFINITY),
        COALESCE(Col2, -BINARY_DOUBLE_INFINITY),
        ..., 
        COALESCE(ColN, -BINARY_DOUBLE_INFINITY)
    )
FROM MY_TABLE

要从查询中删除无限结果,只需添加 where 子句检查所有值是否为空。您也可以使用合并函数来做到这一点:

WHERE COALESCE(Col1, Col2, ..., ColN) IS NOT NULL

1
投票

在三个“合并”调用中按三个顺序使用三个表达式并将它们放入“最少”调用中将得到三个中最少的一个,忽略 null,除非所有三个表达式都为 null。

select least(coalesce(expr1, expr2, expr3), coalesce(expr2, expr3, expr1), coalesce(expr3, expr1, expr2)) from dual

0
投票

一种方法是定义自己版本的

LEAST/GREATEST
func:

-- here version for two params
WITH  FUNCTION least_improved(p1 IN NUMBER, p2 IN NUMBER) RETURN NUMBER IS
BEGIN
    IF p1 IS NULL THEN
       RETURN p2;
    ELSIF p2 IS NULL THEN
       RETURN p1;
    ELSE
       RETURN LEAST(p1, p2);
    END IF; 
END;
SELECT least_improved(col1, col2)
FROM table_name;
/

0
投票

如果您有很多列需要最小值和最大值,您可以将它们取消透视为一列,这样就变得很简单;从单列中排除 NULL 并使用 MIN() 或 MAX() 来获取您想要的内容。

我需要使用大约 50 个日期列(不是一个很好的数据库设计)来完成此操作,UNPIVOT 似乎是最明智/实用的方法


0
投票

你能不能不使用

nvl(Cola,99999)
其中99999是理论最大值,然后使它不再是最小而是现在的理论最大值?


-2
投票
SELECT least(1, 2, 3, nvl(NULL,4)) FROM dual

返回:1

SELECT GREATEST(1, 2, 3, nvl(NULL,0)) FROM dual

返回:3

© www.soinside.com 2019 - 2024. All rights reserved.