【问题标题】:Replace NULL value with previous not null one within given partition用给定分区中的前一个非空值替换 NULL 值
【发布时间】:2020-06-10 17:31:58
【问题描述】:

如何计算新列,其中Number 列中的NULL 值将被先前的非空值替换?不是NULL 的人应该保持不变。都在Customer的分区内。

+----------+------------+--------+
| Customer |    Date    | Number |
+----------+------------+--------+
| A        | 2016-01-01 | 9,00   |
| A        | 2020-01-01 | NULL   |
| A        | 2020-01-15 | 10,00  |
| A        | 2020-02-01 | NULL   |
| A        | 2020-03-01 | NULL   |
| A        | 2020-03-15 | 11,00  |
| A        | 2020-04-01 | NULL   |
| B        | 2016-01-01 | 9,00   |
| B        | 2020-01-01 | NULL   |
| B        | 2020-01-15 | 10,00  |
| B        | 2020-02-01 | NULL   |
| B        | 2020-03-01 | NULL   |
| B        | 2020-03-15 | 11,00  |
| B        | 2020-04-01 | NULL   |
+----------+------------+--------+

假设:

  • 输入数据是ORDER BY Customer, Date,输出也是如此
  • 每个Customer 的第一行(最旧的)将始终具有与NULL 不同的Number

【问题讨论】:

    标签: sql sql-server sql-server-2019


    【解决方案1】:

    如果 SQL Server 支持lag(ignore nulls),这将更容易。但事实并非如此。您可以通过对具有值的行进行累积计数然后传播这些值来定义组:

    select t.*,
           max(number) over (partition by customer, grp)
    from (select t.*, count(number) over (partition by customer order by date) as grp
          from t
         ) t;
    

    您也可以使用 apply 执行此操作,但我怀疑上述方法几乎在所有情况下都更快。

    【讨论】:

      【解决方案2】:
          SELECT customer ,[date] ,case when number is null then B.number else t.number end number
          FROM yourTable t
          CROSS APPLY (
              SELECT TOP 1 number
              FROM yourTable
              WHERE customer = t.customer
                  AND number IS NOT NULL
              ORDER BY DATE DESC
              ) B
      

      【讨论】:

      • 这也可以,但是带有 OVER 的那个更容易合并到我的查询中,这里已经简化了。
      猜你喜欢
      • 2021-06-27
      • 1970-01-01
      • 2021-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      相关资源
      最近更新 更多