【问题标题】:如何选择最后一个不为空的值?
【发布时间】:2021-12-05 21:21:25
【问题描述】:

我有下表:

id a b 
1  1 kate
1  4 null
1  3 paul
1  3 paul
1  2 lola
2  1 kim
2  9 null
2  2 null

结果应该是这样的:

1 3 paul
2 1 kim

我想得到最后一个a,其中b is not null。比如:

select b
from (select,b 
row_num() over (partition by id order by a desc) as num) as f
where num = 1

但是这样我得到一个空值,因为到最后一个a = 4 对应于b IS NULL。也许有一种方法可以从 pandas 重写 ffill 方法?

【问题讨论】:

  • 我认为期望的结果应该是 kim 而不是 kate?

标签: sql postgresql greatest-n-per-group


【解决方案1】:

假设:

  • a 定义为 NOT NULL
  • 你想要a 最大的行,其中b IS NOT NULL - id
SELECT DISTINCT ON (id) *
FROM   tbl
WHERE  b IS NOT NULL
ORDER  BY id, a DESC;

db小提琴here

详细解释:

【讨论】:

    【解决方案2】:

    试试:

    select id, a, b
    from (select id, a, b,
        row_num() over (partition by id order by a desc nulls last) as num
        from unnamedTable) t
    where num = 1
    

    或者,如果这不正确,请尝试使用 nulls first。我永远不记得它与desc 一起使用的方式。

    【讨论】:

    • 我也有同样的想法。不幸的是,空值在 b 列中。
    • 哦,你是对的。在这种情况下,请使用 shawnt00 的answer
    【解决方案3】:

    如果您不能保证每个 id 至少有一个非空值,那么您需要将空值移到列表底部,而不是完全过滤掉这些行。

    select id, a, b
    from (
        select id, a, b, 
            row_number() over (
                partition by id
                order by case when b is not null then 0 else 1 end, a desc
            ) as num
    ) as f
    where num = 1
    

    【讨论】:

      【解决方案4】:

      如果您希望保持原来的列不变,您可以将其包裹在 ctejoin 周围,但看看您的预期输出和逻辑,应该可以这样做。话虽如此,基于row_number() 的方法可能会快一点。

      select distinct 
             id, 
             max(a) over (partition by id) as a, 
             first_value(b) over (partition by id order by a desc) as b
      from tbl
      where b is not null;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-09
        • 2014-11-11
        • 1970-01-01
        • 2015-08-08
        • 2021-02-27
        • 1970-01-01
        • 2017-05-20
        相关资源
        最近更新 更多