当前位置:网站首页>mysql中数据格式转换的一个示例

mysql中数据格式转换的一个示例

2022-06-21 21:21:00 atwdy

背景

工作中遇到的一个需求,把这种存储形式的数据(都是测试数据也不包含什么敏感信息就直接截图了),
在这里插入图片描述
以下面这种形式返回,
在这里插入图片描述
根据表中put_sell字段判定是投放还是卖出,0-投放 1-卖出

对于每天的数据,上面这种是最全的情况,也可能每个asset_scale只有卖出或投放,也可能都没有,像下面这样
在这里插入图片描述

Method 1

最先想到这种思路,简单但有缺陷,直解看代码吧

with t1 as (
	select
		asset_scale,
		(case put_sell when 0 then last_week else 0 end) as last_week_put,
		(case put_sell when 0 then current_week else 0 end) as current_week_put,
		(case put_sell when 1 then last_week else 0 end) as last_week_sell,
		(case put_sell when 1 then current_week else 0 end) as current_week_sell
	from book_management.weekly_asset_put_sell where reportDateId = 20220616
)
select
	asset_scale,
	sum(last_week_put) as last_week_put,
	sum(current_week_put) as current_week_put,
	sum(last_week_sell) as last_week_sell,
	sum(current_week_sell) as current_week_sell	
from t1 group by asset_scale;

执行结果:
在这里插入图片描述

什么缺陷到这儿就能看出来了,就是本应该是空值null的地方都返回了0,原因是因为mysql中的sum求和null并不会引起传播,也就是null会被忽略掉。直白的说,sum列中如果部分值为null,则忽略null,返回非null值的求和结果,如果sum列的值全为null,则返回null。

针对这个特点,上面代码只需要改动一个很小的地方就可以符合需求了,

with t1 as (
	select
		asset_scale,
		(case put_sell when 0 then last_week else null end) as last_week_put,
		(case put_sell when 0 then current_week else null end) as current_week_put,
		(case put_sell when 1 then last_week else null end) as last_week_sell,
		(case put_sell when 1 then current_week else null end) as current_week_sell
	from book_management.weekly_asset_put_sell where reportDateId = 20220616
)
select
	asset_scale,
	sum(last_week_put) as last_week_put,
	sum(current_week_put) as current_week_put,
	sum(last_week_sell) as last_week_sell,
	sum(current_week_sell) as current_week_sell	
from t1 group by asset_scale;

也就是将case when语句中else后面的0全部换成null,执行结果:
在这里插入图片描述
上面代码还可以再精简一下:

select 
	asset_scale,
	abs(sum((case put_sell when 0 then last_week else null end))) as last_week_put,
	abs(sum((case put_sell when 0 then current_week else null end))) as current_week_put,
	abs(sum((case put_sell when 1 then last_week else null end))) as last_week_sell,
	abs(sum((case put_sell when 1 then current_week else null end))) as current_week_sell
from book_management.weekly_asset_put_sell where reportDateId = 20220616 group by asset_scale;

Method 2

思路是将投放与卖出各自过滤出来单独做成一个表,两个表再根据asset_scale做全连接,只不过实现过程中才知道mysql中暂时还不支持full join这种全连接操作,可以用left join+right join+union的方式实现相同效果。

with t1 as (
	select 
		asset_scale,
		last_week as last_week_put,
		current_week as current_week_put
	from book_management.weekly_asset_put_sell where reportDateId = 20220616 and put_sell = 0
),

t2 as (
	select 
		asset_scale,
		last_week as last_week_sell,
		current_week as current_week_sell
	from book_management.weekly_asset_put_sell where reportDateId = 20220616 and put_sell = 1		
)

select  
	t1.asset_scale,
	last_week_put,
	current_week_put,
	last_week_sell,
	current_week_sell
from t1 left join t2 on t1.asset_scale = t2.asset_scale
union
select  
	t1.asset_scale,
	last_week_put,
	current_week_put,
	last_week_sell,
	current_week_sell
from t2 left join t1 on t1.asset_scale = t2.asset_scale;

执行结果:
在这里插入图片描述

感觉这种思路比第一种复杂了一些,主要能理解好全连接这块就没其它问题了。

原网站

版权声明
本文为[atwdy]所创,转载请带上原文链接,感谢
https://blog.csdn.net/atwdy/article/details/125375709