SQL:从具有空值的多个列中选择最小值

时间:2015-04-09 21:07:18

标签: sql select

我有一张像这样的桌子

ID   Col1   Col2   Col3
--   ----   ----   ----
1      7    NULL    12  
2      2     46    NULL
3     NULL  NULL   NULL
4     245     1    792

我想要一个产生以下结果的查询

 ID   Col1   Col2   Col3  MIN
 --   ----   ----   ----  ---
  1     7    NULL    12    7
  2     2     46    NULL   2
  3    NULL  NULL   NULL  NULL
  4    245    1     792    1

我的意思是,我想要一个包含Col1,Col2和Col 3中最小值的列,每行忽略NULL值。在上一个问题(What's the best way to select the minimum value from multiple columns?)中,有一个非NULL值的答案。我需要一个查询尽可能高效的表格。

Select Id,
       Case When Col1 < Col2 And Col1 < Col3 Then Col1
            When Col2 < Col1 And Col2 < Col3 Then Col2 
            Else Col3
            End As MIN
From   YourTableNameHere

6 个答案:

答案 0 :(得分:3)

假设您可以定义一些&#34; max&#34;价值(我在这里使用9999)你的真实价值永远不会超过:

Select Id,
       Case When Col1 < COALESCE(Col2, 9999)
             And Col1 < COALESCE(Col3, 9999) Then Col1
            When Col2 < COALESCE(Col1, 9999) 
             And Col2 < COALESCE(Col3, 9999) Then Col2 
            Else Col3
       End As MIN
    From YourTableNameHere;

答案 1 :(得分:0)

这可能有效:

Select id, Col1, Col2, Col3, least(Col1, Col2, Col3) as MIN From YourTableNameHere

答案 2 :(得分:0)

您没有指定您正在使用的Teradata版本。如果您使用的是版本14+,则可以使用least

不幸的是,least如果其任何参数为null,则返回null。来自文档:

  

LEAST支持1-10个数值。   如果numeric_value是第一个参数的数据类型,则返回   数据类型是数字。输入列表中的其余参数必须   是相同或兼容的类型。如果任一输入参数为NULL,   返回NULL。

但是你可以通过使用coalesce来解决这个问题,就像Joe在答案中所做的那样。

select id, 
  least(coalesce(col1,9999),coalesce(col2,9999),coalesce(col3,9999))
from mytable

答案 3 :(得分:0)

这样您就不需要检查nulls,只需使用minsubquery

select tbl.id,tbl.col1,tbl.col2,tbl.col3,
      (select min(t.col) 
      from ( 
            select col1 as col from tbl_name t where t.id=tbl.id
            union all
            select col2 as col from tbl_name t where t.id=tbl.id
            union all
            select col3 as col from tbl_name t where t.id=tbl.id 
           )t) 
from tbl_name tbl

输出:

1   7       NULL    12      7
2   2       46      NULL    2
3   NULL    NULL    NULL    NULL
4   245     1       792     1

答案 4 :(得分:0)

只需使用coalesce()修改您的查询:

Select Id,
       (Case When Col1 <= coalesce(Col2, col3, col1) And
                  Col1 <= coalesce(Col3, col2, col1)
            Then Col1
            When Col2 <= coalesce(Col1, col3, col2) And
                 Col2 <= coalesce(Col3, col1, col2)
            Then Col2 
            Else Col3
        End) As MIN
From YourTableNameHere;

这不需要发明“魔术”数字或过度复杂的逻辑。

答案 5 :(得分:0)

我发现这个解决方案比使用多个case语句更有效,在评估一行中多个列的数据时,这些子句会非常冗长。

此外,我不能赞同这个解决方案,因为我在大约一年前的某个网站上发现了这个解决方案。今天我需要刷新这个逻辑,我无法在任何地方找到它。我发现了我的旧代码,现在决定在这个论坛上分享它。

创建测试表:

create table #testTable(ID int, Col1 int, Col2 int, Col3 int)
Insert into #testTable values(1,7,null,12)
Insert into #testTable values(2,2,46,null)
Insert into #testTable values(3,null,null,null)
Insert into #testTable values(4,245,1,792)

在行数据中查找最小值:

Select ID, Col1, Col2, Col3 ,(SELECT Min(v) FROM (  VALUES  (Col1), (Col2), (Col3)  ) AS value(v)) [MIN] from #testTable order by ID