【问题标题】:Filling Null Value from Last Not Null Value in Hive从 Hive 中的最后一个非空值填充空值
【发布时间】:2015-09-17 15:27:18
【问题描述】:

我有 4 列

date   number   Estimate   Client    
----   ------
1      3          10        A 
2      NULL       10        Null
3      5          10        A      
4      NULL       10        Null 
5      NULL       10        Null
6      2          10        A   
.......

我需要用新值替换 NULL 值,该值取自日期列中上一个日期中最后一个已知值的值,例如:date=2 number = 3, date 4 and 5 number = 5 and 5。 NULL 值随机出现。

这需要在 Hive 中完成。

【问题讨论】:

    标签: hadoop hive hiveql


    【解决方案1】:

    这是使用标准 hiveql 连接的解决方案。这应该适用于所有版本的配置单元。表 c 合并了不为空的客户端的最近日期。稍后表 d 合并与该日期关联的数字。使用合并附加值仅在数字为空时使用。

    select c.date
    , coalesce(c.number,d.number) as number
    , c.client
    , estimate
    from
        (select date
         , max(prior_date) as prior_date  -- nearest date not null number
         , value
         , estimate
         , a.client
         from
             (select date
               , value
               , estimate
               , client 
               from table_have
             ) a
            left outer join
            (select date as prior_date -- dates without nulls
              , client 
              from table_have 
              where number is not null
            ) b
            on a.client=b.client
            where date > prior_dates
            group by a.client, date, value
       ) c
     left outer join
      (select date
       , number
       , client
       from table_have
       where number is not null
      ) d
      on c.client = d.client and c.prior_date=d.date
      group by c.date, c.client, estimate
    ;
    

    可以通过使用与替代解决方案类似的公用表表达式来进一步优化此查询。但是,此解决方案不需要 N 行重复,并且应该通用。另一个解决方案中所需的数字 N 可能不是静态的,因此该解决方案可能适用于更一般的情况。

    【讨论】:

    • 我留下的解决方案对您有用吗?如果是这样,您能否接受答案,以便社区可以看到问题的解决方案存在。
    【解决方案2】:

    这实际上是一个非常棘手的问题,因为 Hive 不支持递归 CTE 或相关子查询,而这将是解决此类问题的常用方法。

    我能想到的唯一纯粹的 Hive 方法是做一堆自连接。您必须在数据中执行尽可能多的连续空值。

    --add in row numbers
    with T as
    (select select *, row_number() over (order by date) rn
     from mytable)
    --main query
    select T.date, 
           case when T.number is not null then T.number
           else when T1.number is not null then T1.number
           else when T2.number is not null then T2.number end as number
           --repeat this N times 
           --where N is the length of the longest sequece of consectutive nulls 
    
           -- add in your other columns here
    from T 
    join T T1 on T1.date = t.date - 1
    join T T2 on T2.date = t.date - 2
    --repeat this N times
    

    【讨论】:

    • 我们有大约 100 万条记录,您无法预测会有多少空值,因此这不是解决方案
    【解决方案3】:

    这是关于滑动窗口的;

    这是我的表格内容;

    hive> select * from my_table;
    OK
    1       3       10      A
    2       NULL    10      NULL
    3       5       10      A
    4       NULL    10      NULL
    5       NULL    10      NULL
    6       2       10      A
    Time taken: 0.06 seconds, Fetched: 6 row(s)
    

    您需要做的就是在前面和当前行之间的窗口上滑动并找到最近的非空值。 LAST_VALUE 可窗口函数有一个参数可以忽略空值作为布尔值。 LAST_VALUE(<field>,<ignore_nulls> as boolean);

    SELECT
        COALESCE(`date`, LAST_VALUE(`date`, TRUE) OVER(ORDER BY `date` ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)),
        COALESCE(number, LAST_VALUE(number, TRUE) OVER(ORDER BY `date` ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)),
        COALESCE(estimate, LAST_VALUE(estimate, TRUE) OVER(ORDER BY `date` ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)),
        COALESCE(client, LAST_VALUE(client, TRUE) OVER(ORDER BY `date` ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW))
    FROM my_table;
    

    结果将是;

    OK
    1       3       10      A
    2       3       10      A
    3       5       10      A
    4       5       10      A
    5       5       10      A
    6       2       10      A
    Time taken: 19.177 seconds, Fetched: 6 row(s)
    

    【讨论】:

      【解决方案4】:

      如果您使用的是 SQL,那么下面的查询无法提供帮助。否则,您可以使用 pandas ffill 和 bfill 函数。

      select primary_key_val,country,
      COALESCE(country, LAST_VALUE(country, TRUE) OVER(partition by primary_key_val order **by eff_start_dt ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) as upd_country,**
      eff_start_dt from dim_acct_keys order by primary_key_val,eff_start_dt
      

      例如一些数据:

      +------------------+----------+--------------+---------------+
      | primary_key_val  | country  | upd_country  | eff_start_dt  |
      +------------------+----------+--------------+---------------+
      | act1010          | USA      | USA          | 20190101      |
      | act1010          | NULL     | USA          | 20190102      |
      | act1010          | NULL     | USA          | 20190103      |
      | act1012          | USA      | USA          | 20190101      |
      | act1012          | NULL     | USA          | 20190102      |
      | act1012          | MEX      | MEX          | 20190103      |
      

      【讨论】:

        猜你喜欢
        • 2017-07-19
        • 2015-07-22
        • 2021-10-25
        • 1970-01-01
        • 2021-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-05
        相关资源
        最近更新 更多