现在有一张商品入库表,包括商品id、商品成本和入库日期3个字段,由于某些原因,导致部分商品的成本缺失(为0或者没有值都是缺失),这样不利于我们计算成本。所以现在要把缺失的商品进价补充完整,补充的依据是使用相同商品的最近一次有效成本作为当前商品的成本。比如2023-11-04号101商品的cost就需要用300.39填充。
product_id cost date
101 300.39 2023-11-01
102 500 2023-11-02
101 0 2023-11-03
101 2023-11-04
102 600 2023-11-04
102 2023-11-05
103 983 2023-11-06
该场景核心考察的就是开窗函数(last_value)的熟练使用。在同一个窗口内取最后一条有效值作为当前行的值。题不难,但是是一种很好的解题思路。
with temp as
(
select 101 as product_id,300.39 as cost,'2023-11-01' as date
union all
select 102 as product_id,500 as cost,'2023-11-02' as date
union all
select 101 as product_id,0 as cost,'2023-11-03' as date
union all
select 101 as product_id,null as cost,'2023-11-04' as date
union all
select 102 as product_id,600 as cost,'2023-11-04' as date
union all
select 102 as product_id,null as cost,'2023-11-05' as date
union all
select 103 as product_id,983 as cost,'2023-11-06' as date
)
select
product_id
-- last_value第二个参数设置为true,表示取最后一个值时跳过null值。默认不写为false
,last_value(cost,true) over(partition by product_id order by date) as valid_last_value
,date
from(
select
product_id
,if(cost=0 or cost is null,null,cost) as cost --当cost为0或null时就给null值
,date
from temp
) t1
1、last_value函数
在 Hive 中,LAST_VALUE() 是一种窗口函数,用于获取指定列的最后一个值。它的语法如下:
LAST_VALUE(expr,ignore_nulls) OVER (
[PARTITION BY partition_expression, ... ]
ORDER BY sort_expression [ASC|DESC], ...
[ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | range_frame]
)
其中,expr 表示要获取最后一个值的列名或表达式,ignore_nulls 表示是否忽略 NULL 值,如果设置为 true,则 LAST_VALUE() 函数会忽略 NULL 值并返回最后一个非 NULL 值,否则返回 NULL。PARTITION BY 子句用于指定分区字段,ORDER BY 子句用于指定排序规则,ROWS 子句用于指定窗口范围。
SELECT content_id, create_time, value, LAST_VALUE(value, true) OVER (PARTITION BY content_id ORDER BY create_time) as last_value
FROM my_table;
2、first_value函数
在 Hive 中,FIRST_VALUE() 是一种窗口函数,用于获取指定列的第一个值。它的语法如下:
FIRST_VALUE(expr) OVER (
[PARTITION BY partition_expression, ... ]
ORDER BY sort_expression [ASC|DESC], ...
[ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | range_frame]
)
其中,expr 表示要获取第一个值的列名或表达式,PARTITION BY 子句用于指定分区字段,ORDER BY 子句用于指定排序规则,ROWS 子句用于指定窗口范围。FIRST_VALUE() 函数的括号中除了参数 expr 之外,没有其他可选参数。FIRST_VALUE() 函数的主要作用是返回指定列的第一个值,并且不支持忽略 NULL 值。
SELECT content_id, create_time, value, FIRST_VALUE(value) OVER (PARTITION BY content_id ORDER BY create_time) as first_value
FROM my_table;