1. 首先创建对应的数据表
create table col_line_change(name varchar(5),语文 int,英语 int,化学 int,物理 int);
2. 插入对应的数据
insert into col_line_change values('戴憨憨',82,87,73,74);
insert into col_line_change values('溜溜',90,92,76,74);
3. 查询相应数据
select * from col_line_change;
4. 一般的转化方法
select name,'语文' as 科目,语文 as scoure from col_line_change
union
select name,'英语' as 科目,英语 as scoure from col_line_change
union
select name,'化学' as 科目,化学 as scoure from col_line_change
union
select name,'物理' as 科目,物理 as scoure from col_line_change order by name;
5. 进阶方法(json)
之前唐总介绍过使用json类型的方式去做处理也能达到一样的效果,但是也存在一个问题。
select name,(row).key as 科目,(row).value as score from(select name,json_each(json_build_object('语文',"语文",'英语',"英语",'化学',"化学",'物理',"物理"))as row from col_line_change)as st;
结果是相同的,但是问题在哪呢?——是数据类型
用json函数处理过的数据返回的类型是json类型
select (row).key,(row).value,pg_typeof((row).value) from (select json_each(json_build_object('语文',"语文")) as row from col_line_change) as t;;
如果不对结果做二次处理的话这样的结果已经非常完美了,但是如果需要给结果做一些运算,比如给孩子加个附加分什么的,这种情况就需要有一些类型转化了。
但是json类型无法直接转化为int,那么有办法吗?
那必然是有的,毕竟万物皆可text,可以先转换为text再转化为int。
select (row).key,(row).value::text::int+5 as score2 from (select json_each(json_build_object('语文',"语文")) as row from col_line_change) as t;
这样也达到了效果,只不过类型转化次数过多,sql的执行效率并不高。因此我们可以使用第二种方法既达到了转化的效果又保留了原类型。
6.进阶方法(lateral)
SELECT t.name,s.* from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;
再确定一眼类型
SELECT t.name,s.*,pg_typeof(s.score) from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;
计算加减
SELECT t.name,s.科目,s.score+5 from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;
对比两种方法的执行计划看看代价
使用union:
使用json:
使用lateral:
可以清楚的看见lateral的代价更小。
本站文章,未经作者同意,请勿转载,如需转载,请邮件customer@csudata.com.
0 评论
添加一条新评论