【问题标题】:How to write a query to allow null in minimum function如何编写查询以在最小函数中允许 null
【发布时间】:2018-01-31 09:09:28
【问题描述】:

我需要编写一个查询来从表中获取列的最小值,如果该值为空,那么我想包含该行。我写了以下查询,但它忽略了空值。如何修改此查询以在结果中包含空值?

select * from TABLE where COLUMN = (select min(COLUMN) from TABLE );

如果表格如下所示

 |ID  | VALUE | NAME
  101    1      John
  101    null   John
  102    1      Bill
  103    1      Tina
  103    null   Tina
  104    null   James 

结果应该是

|ID  | VALUE | NAME
 101   1       John
 102   1       Bill
 103   1       Tina
 104   null    James 

【问题讨论】:

    标签: sql postgresql h2


    【解决方案1】:

    SQL 服务器

      select DISTINCT j.ID,j.VALUE,j.NAME from  Table1 j
                    join (
                        select id, MIN(VALUE) VALUE from Table1
                        group by id
                    ) as t
                    on t.ID = j.ID and (t.VALUE = j.VALUE or t.VALUE is null)
    

    【讨论】:

      【解决方案2】:

      你需要distinct on:

      with my_table(id, value, name) as (
      values
          (101, 1,    'John'),
          (101, null, 'John'),
          (102, 1,    'Bill'),
          (103, 1,    'Tina'),
          (103, null, 'Tina'),
          (104, null, 'James')
      )
      
      select distinct on (id) *
      from my_table
      order by id, value
      
       id  | value | name  
      -----+-------+-------
       101 |     1 | John
       102 |     1 | Bill
       103 |     1 | Tina
       104 |       | James
      (4 rows)
      

      Distinct on 是 Postgres 特有的出色功能。其他 RDBMS 中的替代方案可能是:

      select t.id, t.value, t.name
      from my_table t
      join (
          select id, min(value) as value
          from my_table
          group by id
      ) u on u.id = t.id and u.value is not distinct from t.value;
      

      注意,您应该使用is not distinct from,因为value 可能为空。

      【讨论】:

      • 这在结果中只给了我一行。我想包含该列的最小值的行以及该列具有空值的行(如果不存在具有最小值的行)。我尝试了 group by 但无法让它工作,因为我需要在 group by 子句中包含 my_column。
      • 谢谢,这很接近。应该怎么做才能从 my_table 中选择 *。如果我在 select 子句中包含两个以上的列,我还需要将它添加到 group by 子句中,这会破坏结果。
      • 好的,在这种情况下我们还有另一个选择。再次查看答案。
      • 是的,这行得通。谢谢!最后一个问题你知道 h2 中是否允许使用不同的 on 子句吗?我需要能够在 h2 和 postgres 中运行此查询。
      • 我不这么认为,请参阅答案寻找替代方案。
      【解决方案3】:

      我希望这能解决您的问题。

      SELECT id,
         CASE WHEN MIN(
               CASE WHEN value IS NULL THEN 0 ELSE 1 END) = 0 THEN null
         ELSE MIN(value) END
      FROM tableName
      GROUP BY id
      

      或使用COALESCE

      SELECT id,
         CASE WHEN MIN(COALESCE(value, 0)) = 0 THEN null
         ELSE MIN(value) END
      FROM tableName
      GROUP BY id
      

      我现在在手机上,所以我无法测试。

      【讨论】:

      • 查看我更新的问题。我要么获得所有空行,要么获得所有具有最小值的行,但不能同时获得两者。我需要具有最小值的行以及具有空值的行(如果它没有最小值)
      • 谢谢 - 它不一定会在结果中保留具有最小值的行。
      【解决方案4】:

      如果你想用户order by:

      select t.*
      from t
      order by t.column asc nulls first
      limit 1;
      

      或者,使用rank():

      select t.*
      from (select t.*,
                   rank() over (order by col asc nulls first) as seqnum
            from t
           ) t
      where seqnum = 1;
      

      【讨论】:

      • 查看我更新的问题。我要么获得所有空行,要么获得所有具有最小值的行,但不能同时获得两者。我需要具有最小值的行以及具有空值的行(如果它没有最小值)
      【解决方案5】:
      with c as (
          select column as c
          from table
          order by column nulls first
          limit 1
      )
      select *
      from table cross join c
      where column = c or column is null
      

      【讨论】:

      • 查看我更新的问题。我要么获得所有空行,要么获得所有具有最小值的行,但不能同时获得两者。我需要具有最小值的行以及具有空值的行(如果它没有最小值)
      【解决方案6】:

      您不能对 null 值执行等于 (=),您必须检查 is null 左右。所以一个简单的解决方案是将null 值默认为一个不会被使用的数字:

      select * from TABLE where coalesce(COLUMN, -9999) = (select min(coalesce(COLUMN,-9999)) from TABLE );
      

      coalesce 函数返回传递给它的第一个非空值。

      【讨论】:

      • 查看我更新的问题。我要么获得所有空行,要么获得所有具有最小值的行,但不能同时获得两者。我需要具有最小值的行以及具有空值的行(如果它没有最小值)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多