如何在SQL中的一个特定行中找到最少的非空列?

Ant*_*pos 13 mysql sql

我试图找到同一个表中一行的两列中的最小数字,但需要注意的是其中一列可能在特定行中为空.如果其中一列为null,我希望为该行返回的另一列中的值,因为在这种情况下,这是最低的非空列.如果我在MySQL 5.1中使用least()函数:

select least(1,null)
Run Code Online (Sandbox Code Playgroud)

这返回null,这不是我想要的.在这种情况下,我需要查询返回1.

我已经能够通过这个查询获得我想要的结果:

select least(coalesce(col1, col2)) , coalesce(col2,col1))
Run Code Online (Sandbox Code Playgroud)

只要col1和col2都不为null,每个coalesce语句将返回一个数字,而least()处理查找最低值.

有更简单/更快的方法吗?我在这个例子中使用MySQL,但欢迎使用通用解决方案.

Iva*_*sov 16

不幸的是(对于您的情况)LEAST的行为在MySQL 5.0.13(http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_least)中发生了变化- 它仅用于返回NULL如果所有参数都为NULL.

这个更改甚至被报告为一个错误:http://bugs.mysql.com/bug.php?id = 15610 但是修复只针对MySQL文档,解释了新行为和兼容性中断.

您的解决方案是推荐的解决方法之一.另一个可以使用IF运算符:

SELECT IF(Col1 IS NULL OR Col2 IS NULL, COALESCE(Col1, Col2), LEAST(Col1,Col2))
Run Code Online (Sandbox Code Playgroud)

  • 很棒的信息,但该解决方法仅适用于 2 个值,如果您添加一个 `Col3`,它将不再起作用。在这种情况下,这是解决方法:`LEAST(COALESCE(a,b,c), COALESCE(b,c,a), COALESCE(c,a,b))` 这将变得非常混乱,例如 10 列。让我们希望有一天能添加一个 `NLEAST()` 函数...... (3认同)

Pau*_*gel 10

这就是我解决它的方法:

select coalesce(least(col1, col2), col1, col2)
Run Code Online (Sandbox Code Playgroud)

如果一个值为 NULL,查询将返回第一个非 NULL 值。如果两个值都可以为 NULL,您甚至可以添加默认值作为最后一个参数。


pat*_*ato 5

根据您将所有值都设为的极端情况null,我会选择这样的语法,它更具可读性(如果您只有两列,则更简单的解决方案如下!)

SELECT LEAST( IFNULL(5, ~0 >> 1), IFNULL(10, ~0 >> 1) ) AS least_date;
-- Returns: 5

SELECT LEAST( IFNULL(null, ~0 >> 1), IFNULL(10, ~0 >> 1) ) AS least_date;
-- Returns: 10

SELECT LEAST( IFNULL(5, ~0 >> 1), IFNULL(null, ~0 >> 1) ) AS least_date;
-- Returns: 5

SELECT LEAST( IFNULL(null, ~0 >> 1), IFNULL(null, ~0 >> 1)) AS least_date
-- Returns: @MAX_VALUE (If you need to use it as default value)

SET @MAX_VALUE=~0 >> 1;
SELECT LEAST( IFNULL(null, @MAX_VALUE), IFNULL(null, @MAX_VALUE)) AS least_date;
-- Returns: @MAX_VALUE (If you need to use it as default value). Variables just makes it more readable!

SET @MAX_VALUE=~0 >> 1;
SELECT NULLIF(
    LEAST( IFNULL(null, @MAX_VALUE), IFNULL(null,@MAX_VALUE)),
    @MAX_VALUE
) AS least_date;
-- Returns: NULL
Run Code Online (Sandbox Code Playgroud)

这是我的首选方式,如果

  • 您可以确保至少一列不能 NULL
  • 在极端情况下(所有列都是NULL),您需要一个非空默认值,该值大于任何可能的值或可以限制为某个阈值
  • 您可以处理变量以使此语句更具可读性

如果你问自己是什么~0 >> 1意思:这只是“给我可用的最大数量”的简写。另见:https : //stackoverflow.com/a/2679152/2427579

更好的是,如果您只有两列,则可以使用:

SELECT LEAST( IFNULL(@column1, @column2), IFNULL(@column2, @column1) ) AS least_date;
-- Returns: NULL (if both columns are null) or the least value
Run Code Online (Sandbox Code Playgroud)