暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Sql进阶技巧:如何分析商品入库采购成本数据缺失问题?| 近距离有效的数据缺失值填充问题

原创 江月明 2024-08-24
309

0 场景描述


有一张入库成本表,一个商品每次入库就会产生一条数据,里面包含商品id,入库时间,以及入库采购的成本.但由于某些某些原因,导致表中某些数据的成本是有丢失的.现在的逻辑是,当成本丢失时,有两种取成本的方式,现在需要把两种成本都取出来,最后取2次成本的平均值作为本次入库的成本。取数逻辑如下:

1.取同一个商品最近一次入库的有效成本(即存在成本时就为有效成本,无效成本为null)
2.取同一个商品紧接着一次入库的有效成本
3 上述中结果依然有无效值时,记为0



1 数据准备

Hive开发环境

create table cost as (

       select stack(
	   
	                14,
			'1101', '2021-01-01' , 120    ,
	                '1102', '2021-01-01' , 150    ,
	                '1102', '2021-01-02' , null   ,
	                '1102', '2021-01-03' , null   ,
	                '1102', '2021-01-04' , 200    ,
	                '1102', '2021-01-05' , 210    ,
                        '1103', '2021-01-06' , 300    ,
                        '1103', '2021-01-07' , null   ,
                        '1103', '2021-01-08' , 400    ,  
                        '1104', '2022-01-01' , 111111 ,
                        '1104', '2022-01-02' , null   ,
                        '1104', '2022-01-03' , null   ,
                        '1104', '2022-01-04' , 22222  ,
                        '1104', '2022-01-05' , null   
					                   ) as (product_id,into_warehouse_time,cost)                    

);

2 数据分析

方法1:断点分组思想【通用解法】

难点:如何存在多个NULL值时能正确取到最近上一次有效值,和最近的下一次的有效值。

如果为null的能和最近一次上一个有效的数据分到一个组里,或和最近一次有效的下一条数据分到一个组里,问题就好解决了。那么怎么分组呢?我们采用断点分组的思想来解决

核心逻辑如下:

--将NULL值最近上一个分到一个组里

sum(if(cost is null,0,1)) over(partition by product_id order by into_warehouse_time) as grp_flg1

--将NULL值最近下一个分到一个组里

sum(if(cost is null,0,1)) over(partition by product_id order by into_warehouse_time desc) as grp_flg2

上述逻辑可以进一步优化,我们观察到数据的特征,由于存在NULL值,表示稀疏的,可以利于count(字段) 忽略NULL值得特性,利用count()函数的分析函数来显示条数的变化来达到同样的结果,具体优化SQL如下:


 count(cost) over (partition by product_id order by into_warehouse_time)      as grp_flg1

 count(cost) over (partition by product_id order by into_warehouse_time desc) as grp_flg2


最终完整的SQL如下:


select product_id
     , into_warehouse_time
     , coalesce(cost, (last_cost + next_cost) / 2,0) cost
from (select product_id
           , into_warehouse_time
           , cost
           , COALESCE(max(cost) over (partition by product_id,grp_flg1), 0)  as last_cost
           , COALESCE(max(cost) over (partition by product_id,grp_flg2 ), 0) as next_cost
      from (SELECT product_id
                 , into_warehouse_time
                 , cost
                 , count(cost) over (partition by product_id order by into_warehouse_time)      as grp_flg1
                 , count(cost) over (partition by product_id order by into_warehouse_time desc) as grp_flg2
            from cost
            ) t
      ) t
order by product_id,into_warehouse_time



方法2:优雅解法 | last_value分析函数忽略NULL值特性实现

利用last_value(a,true) over(order by b)求解,如果该函数第二个参数为true,则按照order by指定的顺序获取距离当前行最近且值不为NULL的一行对应字段值,oracle数据库则使用last_value(a ignore nulls) over(order by b) 语法,另外oracle数据库lag函数的分析函数,也可以忽略null值,实际上对该问题lag函数更为精确,而对于Hive数据库中则lag()函数的分析函数没有忽略NULL值这一特性,只能使用last_value分析函数。

具体求解SQL如下:

select product_id
     , into_warehouse_time
     , coalesce(cost, (NVL(last_cost, 0) + NVL(next_cost, 0)) / 2, 0) as cost
from (select cost.*
           , last_value(cost, true) over (partition by product_id order by into_warehouse_time)      last_cost
           , last_value(cost, true) over (partition by product_id order by into_warehouse_time desc) next_cost
      from cost) t
order by product_id, into_warehouse_time;

3 小结

本文分析了一种商品入库采购成本数据缺失用有效值填充的问题,该问题在数据清洗中比较常见,文章中给出了两种解题思路,一种利用断点分组的思路,一种利用last_value()忽略NULL值的思路,第二种方法较为优雅。


原文链接:Sql进阶技巧:如何分析商品入库采购成本数据缺失问题?| 近距离有效的数据缺失值填充问题


本篇文章收录于CSDN 莫叫石榴姐 数字化建设通关指南 中,也欢迎大家去我的公众号“会飞的一十六”进行交流



最后修改时间:2024-08-24 14:40:04
文章转载自江月明,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论