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

问题描述:

我试图找到同一个表中某一行的两列中的最小数字,并注意其中一列可能在特定行中为空。如果其中一列为空,我希望为该行返回另一列中的值,因为这是此例中最低的非空列。如果我使用MySQL 5.1中最少()函数:如何在SQL中的某个特定行中查找最少的非空列?

select least(1,null) 

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

我已经能够得到我想要的,一般与此查询结果:

select least(coalesce(col1, col2)) , coalesce(col2,col1)) 

只要col1和col2上都是不为空每个凝聚语句将返回一个数字,最少( )处理找到最低。

有没有更简单/更快的方法来做到这一点?在这种情况下,我使用的是MySQL,但欢迎使用一般解决方案。

+1

快?你确定它慢? – 2010-06-20 06:03:05

+0

还没有判断它一定很慢,但它调用了3个函数,而不是可能的一个。我在按照我需要尽可能快的查询的子句中使用它。 – 2010-06-20 06:08:44

不幸(对于你的情况)LEAST的行为在MySQL 5.0.13(http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_least)中发生了变化 - 只有在所有参数都为NULL的情况下,它才返回NULL。

这个变化甚至被报告为一个bug:http://bugs.mysql.com/bug.php?id=15610 但是这个修复只是为了解释新的行为和兼容性问题。

您的解决方案是推荐的解决方法之一。另一个可以使用IF操作:

SELECT IF(Col1 IS NULL OR Col2 IS NULL, COALESCE(Col1, Col2), LEAST(Col1,Col2)) 

这可以执行好一点(可能要转换成相应的MySql语法):

SELECT 
    CASE 
    WHEN Col1 IS NULL THEN Col2 
    WHEN Col2 IS NULL THEN Col1 
    ELSE Least(Col1, Col2) 
    END 

另一种方法(可能比较慢,虽然,但值得一试):

SELECT Col1 
WHERE Col2 IS NULL 
UNION 
SELECT Col2 
WHERE Col1 IS NULL 
UNION 
SELECT least(Col1, Col2) 
WHERE Col1 IS NOT NULL AND Col2 IS NOT NULL 

根据其所有值是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 

这是我的,如果

  • 可以保证至少有一列首选方式不能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 

为什么不设置一个列的值等于其他列时,它的空?

SELECT LEAST(IFNULL(COL1, COL2), IFNULL(COL2, COL1)); 

用上面的代码,空值将被忽略,除非两者都为空。

例如

COL1 = NULL,COL2 = 5

LEAST(IFNULL(NULL, 5), IFNULL(5, NULL)) -> LEAST(5, 5) -> 5 

COL1 = 3,COL2 = NULL

LEAST(IFNULL(3, NULL), IFNULL(NULL, 3)) -> LEAST(3, 3) -> 3 

COL1 = NULL,COL2 = NULL

LEAST(IFNULL(NULL, NULL), IFNULL(NULL, NULL)) -> LEAST(NULL, NULL) -> NULL