【问题标题】:How to update 0 or null values with sequence number?如何使用序列号更新 0 或空值?
【发布时间】:2019-12-09 20:32:32
【问题描述】:

我需要更新列批处理中的值 0 和 null,以便该值继续该年的序列。新值应从当年最低的 0/null 值开始。

id year batch
1  2005 null
2  2005 1
3  2005 2
4  2005 0
5  2006 0
6  2006 1
7  2006 2
8  2006 3
9  2006 null
10 2006 0

结果应该如下:

id year batch
1  2005 3
2  2005 1
3  2005 2
4  2005 4
5  2006 4
6  2006 1
7  2006 2
8  2006 3
9  2006 5
10 2006 6

你有什么想法吗?我相信我必须使用 MAX 值,但不知道如何继续。

【问题讨论】:

  • 使用lag函数和exists

标签: sql postgresql window-functions


【解决方案1】:

您可以使用窗口函数row_number生成一个新序列并更新表中的数据。

假设您的表名为test

UPDATE test 
set batch = new_batch
FROM (
  SELECT 
    id
  , year
  , ROW_NUMBER() over (partition BY year ORDER BY  NULLIF(batch, 0), id) new_batch
  FROM test
) new_values
WHERE new_values.id = test.id

NULLIF 函数将表达式的结果设置为 null 如果它计算为第二个参数。在此示例中,如果批次为 0,则将其设置为空。默认情况下,空值按顺序放在最后,您也可以使用 NULLS LAST 显式指定。

基于滞后的解决方案在 postgresql 中不起作用,因为 postgresql 不支持滞后/领先窗口函数中的限定符 ignore nulls。虽然这种方法在其他数据库中有效。

【讨论】:

    【解决方案2】:

    你可以使用count(..) over partition by .. order by ..解析函数:

    select id, year,
           count(id) over 
           (partition by year
            order by year, sign( coalesce(batch,0) ) desc, id ) as batch
      from t
     order by id
    

    我们需要使用 (sign( coalesce(batch,0) ) desc) 在 batchnon-nullnon-zero 值之后开始计数,这应该是 (id) 的顺序,并且这个计数应该重置每年(partition by year)按年份顺序排列(order by year

    Demo

    如果您不仅要显示还想更新,请使用:

    update t t1
       set batch = t2.batch
      from ( select id,
                    count(id) over 
                            (partition by year
                             order by coalesce(batch,0) , id ) as batch
                       from t
                       ) as t2
    where t1.id = t2.id   
    

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 2018-10-05
      • 2013-12-14
      • 1970-01-01
      • 2019-04-23
      • 2011-09-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      相关资源
      最近更新 更多