【问题标题】:SQL fill NULL row with previous non NULL rowSQL 用前一个非 NULL 行填充 NULL 行
【发布时间】:2020-09-02 11:11:15
【问题描述】:

所以我有一个 bq 表,它被创建为几个日历日期快照,连接到 trx 数据。请查找以下查询以填充表格

  SELECT
    GENERATE_DATE_ARRAY(date_add(DATE(CURRENT_TIMESTAMP), interval -20 day), DATE('2020-08-22')) AS date_array
  )
         
 ,dim_date AS (
  SELECT
    sn_date
  FROM
    date_array_table,
    UNNEST(date_array) AS sn_date
    )
  
 ,data_test as (
 select date('2020-08-20') as date, 1 as id, 1000 as num
 UNION ALL
 select date('2020-08-18') as date, 1 as id, 130 as num
 UNION ALL
 select date('2020-08-18') as date, 2 as id, 300 as num
 UNION ALL
 select date('2020-08-13') as date, 2 as id, 250 as num
 )

 ,jjoin as (
 select
 *
 from dim_date
 left join 
 data_test
 on 1=1 and sn_date = date
 )

 select *
 from jjoin
 order by 1 desc

结果如下img

下一步我想用 NULL 值填充快照行,每个 id 按日期前一个非 NULL 行。我尝试使用 max 或 first_value 但它仍然为 NULL。示例:

select sn_date
coalesce(num, max (num) over (partition by id order by date)
from jjoin

但它不显示之前的非空行。有什么建议吗?谢谢

预期:

--------------------------
sn_date | date | id | num
--------------------------
08/22   | 08/20| 1  | 1000
08/21   | 08/20| 1  | 1000
08/20   | 08/20| 1  | 1000
08/19   | 08/18| 1  | 130
08/18   | 08/18| 1  | 130
08/18   | 08/18| 2  | 300
08/17   | 08/13| 1  | 250
08/16   | 08/13| 1  | 250
08/15   | 08/13| 1  | 250

【问题讨论】:

    标签: sql google-bigquery null snapshot coalesce


    【解决方案1】:

    你可以使用last_value():

    select sn_date, date, id, num,
           last_value(date ignore nulls) over (order by date desc),
           last_value(id ignore nulls) over (order by date desc),
           last_value(num ignore nulls) over (order by date desc)
    

    我应该注意到,SQL 标准支持 lag() 上的 ignore nulls 以及 first_value()last_value()。当我考虑解决这个问题时,我想到的是lag()。我认为 BigQuery 是唯一支持 ignore nulls 但不支持 lag() 的数据库。

    【讨论】:

    • 我试过了,但它似乎只取了 id 2 中的最后一个值。我尝试按 id 添加分区,但改为给出 NULL
    • @Elbert 。 . .我跑了这个,它奏效了。你确定你有desc 吗?在我最初回答几分钟后,我在编辑中添加了这一点。正如我在答案中所说,我认为lag() 没有降序排列;但是last_value() 的顺序需要颠倒。我还应该补充一点,我在生产代码中经常使用这个结构,所以我知道它有效。
    • 是的,你是对的。忘记更新页面。谢谢!
    【解决方案2】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    SELECT sn_date, 
      FIRST_VALUE(date IGNORE NULLS) OVER (win) AS date,
      FIRST_VALUE(id IGNORE NULLS) OVER (win) AS id,
      FIRST_VALUE(num IGNORE NULLS) OVER (win) AS num
    FROM your_current_result
    WINDOW win AS (ORDER BY sn_date DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
    

    如果适用于问题中显示的当前结果,如下例所示

    #standardSQL
    WITH your_current_result AS (
      SELECT DATE '2020-08-20' sn_date, DATE '2020-08-20' date, 1 id, 1000 num UNION ALL
      SELECT '2020-08-22', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-21', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-19', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-18', '2020-08-18', 1, 130 UNION ALL
      SELECT '2020-08-18', '2020-08-18', 2, 300 UNION ALL
      SELECT '2020-08-17', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-16', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-15', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-14', NULL, NULL, NULL UNION ALL
      SELECT '2020-08-13', '2020-08-13', 1, 250 
    )
    SELECT sn_date, 
      FIRST_VALUE(date IGNORE NULLS) OVER (win) AS date,
      FIRST_VALUE(id IGNORE NULLS) OVER (win) AS id,
      FIRST_VALUE(num IGNORE NULLS) OVER (win) AS num
    FROM your_current_result
    WINDOW win AS (ORDER BY sn_date DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
    

    结果是

    Row sn_date     date        id  num  
    1   2020-08-22  2020-08-20  1   1000     
    2   2020-08-21  2020-08-20  1   1000     
    3   2020-08-20  2020-08-20  1   1000     
    4   2020-08-19  2020-08-18  1   130  
    5   2020-08-18  2020-08-18  1   130  
    6   2020-08-18  2020-08-18  2   300  
    7   2020-08-17  2020-08-13  1   250  
    8   2020-08-16  2020-08-13  1   250  
    9   2020-08-15  2020-08-13  1   250  
    10  2020-08-14  2020-08-13  1   250  
    11  2020-08-13  2020-08-13  1   250  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多