Flink SQL 如何实现列转行 ?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flink SQL 如何实现列转行 ?相关的知识,希望对你有一定的参考价值。

参考技术A 在 SQL 任务里面经常会遇到一列转多行的需求,下面就来总结一下在 Flink SQL 里面如何实现列转行的,先来看下面的一个具体案例.

原始数据格式如下:

现在希望得到的数据格式是这样的:

这是一个典型的列转行或者一行转多行的场景,需要将 data 列进行拆分成为多行多列,下面介绍两种实现方式.

这里在定义 data 字段类型的时候直接定义为 ARRAY 类型,因为 unnest 函数需要一个数组类型的参数.

自定义表值函数(UDTF),自定义表值函数,将 0 个、1 个或多个标量值作为输入参数(可以是变长参数)。与自定义的标量函数类似,但与标量函数不同。表值函数可以返回任意数量的行作为输出,而不仅是 1 个值。返回的行可以由 1 个或多个列组成。调用一次函数输出多行或多列数据。必须继承 TableFunction 基类,并实现一个或者多个名为 eval 的方法, 在使用 UDTF 时,需要带上 LATERAL TABLE两个关键字.

自定义 UDTF 解析的时候,就不需要把 data 字段定义成 ARRAY 类型了,直接定义成 STRING 类型就可以了,并且这种方式会更加的灵活,比如还需要过滤数据或者更复杂的一些操作时都可以在 UDTF 里面完成.

unnest 和 自定义 UDTF 函数在使用的时候都有 3 种写法,前面两种写法的效果其实是一样的,第三种写法相当于 left join 的用法.区别在于 CROSS JOIN/INNER JOIN: 对于左侧表的每一行,右侧 UDTF 不输出,则这一行不输出.LEFT JOIN: 对于左侧表的每一行,右侧 UDTF 不输出,则这一行会输出,右侧 UDTF 字段为 null

在实际使用的时候如果 unnest 可以满足需求就直接用 unnest 不需要带来额外的开发,如果 unnest 函数满足不了需求,那么就自定义 UDTF 去完成.

oracle 列转行

有两张表
A 产品表
产品名称,产品编码
产品1 001

B销量表
产品编号 月份 销量
001 1 1000
001 2 2000
001 3 3000
。。。。。。
001 12 12000

通过sql语句如何输出

产品名称 产品编号 1月 2月 3月 。。。。。12月
产品1 001 1000 2000 3000 。。。。 12000

最后请教一个设计表的问题。想这种情况是如上表结构比较好呢?还是将B表设计为
产品编号 1月 2月 3月 。。。。。12月

我觉得设计成一张表就够了,比如table:AB吧然后用游标实现 ,
create or replace procedure ptest as
strname varchar2(30);
str varchar2(1000);
strid varchar2(10);
cursor cur is select * from AB;
begin
str:='';
open cur;
loop
fetch cur into strid,strname;
exit when cur%notfound;
str:=str||strname||',';
end loop;
str:=substr(str,1,length(str)-1);
dbms_output.put_line(str);
end;
参考技术A 基本思路是运用case when语句,最好把创建表的语句给出(可用dbms_metadata.get_ddl,运行前把long设置大点)。

自己利用示例表得出需求,可以根据你自己的表来进行修改:

demo@ORCL>select max(case when deptno=10 then ename else null end) as "部门10",
max(case when deptno=20 then ename else null end) as "部门20",
max(case when deptno=30 then ename else null end) as "部门30"
from
(select deptno,ename,row_number() over(partition by deptno order by ename) rn from emp) x
group by rn order by 1,2,3;

部门10 部门20 部门30
---------- ---------- ---------
CLARK ADAMS ALLEN
KING FORD BLAKE
MILLER JONES JAMES
SCOTT MARTIN
SMITH TURNER
WARD
参考技术B oracle下可以用函数decode处理:

select t1.产品名称,t1.产品编号,
sum(decode(t2.月份,1,t2.销量,0)) 1月,
sum(decode(t2.月份,2,t2.销量,0)) 2月,
sum(decode(t2.月份,3,t2.销量,0)) 3月,
sum(decode(t2.月份,4,t2.销量,0)) 4月,
...
sum(decode(t2.月份,11,t2.销量,0)) 11月,
sum(decode(t2.月份,12,t2.销量,0)) 12月
from 产品表 t1, 销量表 t2
where t1.产品编码=t2.产品编码
group by t1.产品名称,t1.产品编号;

一般设计成你现有这样的结构就可以了.因为销量表是个明细记录表,记录数比较大.
参考技术C select a.产品名称,b.产品编码, wmsys.wm_concat(销量) from 产品表 a, 销量表 b where a.产品编号 = b.产品编码 group by a.产品名称 ,b.产品编码

以上是关于Flink SQL 如何实现列转行 ?的主要内容,如果未能解决你的问题,请参考以下文章

Flink实战系列Flink SQL 字符串类型的字段如何实现列转行?

sql语句列转行

sql语句列转行

Oracle列转行,行转列

oracle 列转行

Hive 行转列 & 列转行