SQL从具有空值的行数据中选择MIN值

Posted

技术标签:

【中文标题】SQL从具有空值的行数据中选择MIN值【英文标题】:SQL Selecting MIN value from row data with null values 【发布时间】:2012-08-17 16:45:15 【问题描述】:

我在Oracle中的表是这样的

Col   Col1  Col2  Col3  ColR
--   ----  ----   ----  ---- 
30    73    40    null  -10
60    32    null  20     40
90    80    null  null   10
80    45    81    30     50

我也可以在上面的列中设置 0 而不是 null。 我需要从 Col1、Col2、Col3 中找到最小值,忽略 null 或 0,并通过从 Col 中减去来填充 ColR。

编辑: 我写了一个 CASE 语句,由于我的表中的空值而不起作用。

 SELECT col,col1,col2,col3,
  CASE
    WHEN Col1 < Col2 AND Col1  < Col3
    THEN Col - Col1
    WHEN Col2 < Col1 AND Col2  < Col3
    THEN Col - Col2
    ELSE Col - Col3
  END ColR
FROM
 (SELECT col,col1,
   CASE
    WHEN col22 IS NULL
    THEN NULL( i can also SET TO 0 but it will mess  WITH my other calculation TO find MIN)
      ELSE ROUND( 100* ( (col22) / (col44)))
    END col2 ,
    CASE
      WHEN col33 IS NULL
      THEN NULL
      ELSE ROUND( 100* ( (col33) / (col44)))
    END col3
  FROM TABLE
  )

我刚刚在我的选择查询中包含了 case 语句。所有列值都从另一个查询中填充。

【问题讨论】:

如果所有三列都为空(或 0)会怎样? 50 - 40 = -10 是错字吗? 另外,你至少可以在case语句之外提取col的提及。 【参考方案1】:

听起来你想要类似的东西

SELECT least( (case when col1 is null or col1 = 0 then 999999999 else col1 end),
              (case when col2 is null or col2 = 0 then 999999999 else col2 end),
              (case when col3 is null or col3 = 0 then 999999999 else col3 end) )
  FROM <<table name>>

其中 999999999 是一个足够大的数值,它总是大于任何其他有效值。如果所有三列都可能具有 NULL 或 0 值,那么您可能需要添加一个额外的检查,如果该 least 函数的结果是 999999999 您返回 0 或 NULL 或其他否则有意义。

@X-Zero 很乐意将这个构造的 SQL Fiddle example 组合在一起。请注意,他的示例是过滤掉所有三列都具有 NULL 或 0 值的行。

【讨论】:

我不知道Oracle有相关的多参数最小值函数(DB2重用MAX()函数)!我会添加一个答案,但它本质上是这样的,所以有一个工作 SQL Fiddle example 代替,完成空行忽略。 @X-Zero - 感谢您的示例!我在答案中添加了一个链接。【参考方案2】:

// 如果您需要 COL1 或 COL(任何列)中的 MINIMAL

SELECT MIN (COL1) FROM (SELECT * FROM TABLE WHERE COL1 IS NOT NULL)

您能否详细说明一下,我实际上无法为您提供这一小部分信息。

【讨论】:

【参考方案3】:

Oracle NVL 用法:

nvl(check_expression, replacement_value)

所以 nvl(col2,0) 应该采用会影响您数学的空值。

那就试试吧:

CASE
       WHEN nvl(col1,0) < nvl(col2,0) AND nvl(col1,0) < nvl(col3,0)
       THEN Col - nvl(col1,0)
       WHEN  nvl(col2,0) < nvl(col1,0) AND nvl(col2,0) < nvl(col3,0)
       THEN Col - nvl(col2,0)
       ELSE Col - nvl(col3,0)
END ColR 

编辑:我错过了 X-Zero 的观点。我认为,如果您将 NULLS 替换为 9999999 而不是 0,则逻辑将起作用,尽管这可能对该示例数据过于具体,而不是现实世界的解决方案。

【讨论】:

除非他想忽略 nulls/0 只要 col1 到 col3 都不是负数。 :( 如果这就是 OP 所说的,那么 @Cody 似乎有一个观众 我已经修改了查询,我想忽略甚至 0 @Tony Hopkinson - 是的,我认为科迪和我可能通过不同的路径同时到达了 999999。【参考方案4】:

如果您想忽略列中的空值,可以使用 NVL 函数将它们包装起来。这会将列中的空值替换为指定的值,您可以为此使用一些大数字。例如:NVL(col1,99999)

Oracle 数据库 SQL 参考 - NVL:http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm

【讨论】:

以上是关于SQL从具有空值的行数据中选择MIN值的主要内容,如果未能解决你的问题,请参考以下文章

返回 SQL 中返回空值的行?显示它们不是空白值

如何从计数中选择具有最大产生值的行

如何获取 SQL 中具有 MAX 和 MIN 值的行的 ID

选择可能具有相同值的行的多个实例

PostgreSQL 查询列上具有最小空值的行

SQL 中的 LISTAGG 返回具有空值的行