1. 首先创建对应的数据表

  1. create table col_line_change(name varchar(5),语文 int,英语 int,化学 int,物理 int);

2. 插入对应的数据

  1. insert into col_line_change values('戴憨憨',82,87,73,74);
  2. insert into col_line_change values('溜溜',90,92,76,74);

3. 查询相应数据

  1. select * from col_line_change;

4. 一般的转化方法

  1. select name,'语文' as 科目,语文 as scoure from col_line_change
  2. union
  3. select name,'英语' as 科目,英语 as scoure from col_line_change
  4. union
  5. select name,'化学' as 科目,化学 as scoure from col_line_change
  6. union
  7. select name,'物理' as 科目,物理 as scoure from col_line_change order by name;

5. 进阶方法(json)
之前唐总介绍过使用json类型的方式去做处理也能达到一样的效果,但是也存在一个问题。

  1. 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类型

  1. 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。

  1. 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)

  1. SELECT t.name,s.* from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;

再确定一眼类型

  1. SELECT t.name,s.*,pg_typeof(s.score) from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;

计算加减

  1. SELECT t.name,s.科目,s.score+5 from col_line_change t JOIN LATERAL(VALUES('语文',t.语文 ), ('英语',t.英语), ('化学',t.化学),('物理',t.物理)) s(科目, score) on true;

对比两种方法的执行计划看看代价
使用union:
union
使用json:
json
使用lateral:
lateral

可以清楚的看见lateral的代价更小。

本站文章,未经作者同意,请勿转载,如需转载,请邮件customer@csudata.com.
0 评论  
添加一条新评论