select id
,keyvalue(column_value,'name')as name
,keyvalue(column_value,'age')as age
from(select id
,wm_concat(';',concat(obj_name,':',obj_value))as column_value
from school
groupby id
);
SELECT id,'数学'AS subject, 数学 AS score FROM student_scores_pivot
UNIONALLSELECT id,'语文'AS subject, 语文 AS score FROM student_scores_pivot
UNIONALLSELECT id,'英语'AS subject, 英语 AS score FROM student_scores_pivot
ORDERBY id, subject;
2.2、使用 CROSS JOIN + 条件筛选
优点是不用频繁读取磁盘
SELECT
s.id,
c.subject,CASE c.subject
WHEN'数学'THEN s.数学
WHEN'语文'THEN s.语文
WHEN'英语'THEN s.英语
ENDAS score
FROM student_scores_pivot s
CROSSJOIN(SELECT'数学'AS subject UNIONALLSELECT'语文'UNIONALLSELECT'英语') c;
同样的语句,使用values和row
SELECT
s.id,
c.subject,CASE c.subject
WHEN'数学'THEN s.数学
WHEN'语文'THEN s.语文
WHEN'英语'THEN s.英语
ENDAS score
FROM student_scores_pivot s
CROSSJOIN(valuesrow('数学'),row('语文'),row('英语')) c(subject);
DELIMITER//CREATEPROCEDURE dynamic_pivot(IN table_name VARCHAR(100),IN row_id VARCHAR(100),IN pivot_col VARCHAR(100),IN value_col VARCHAR(100))BEGINDECLARE done INTDEFAULTFALSE;DECLARE col_name VARCHAR(100);DECLARE col_list TEXTDEFAULT'';DECLARE cur CURSORFORSELECTDISTINCT pivot_col FROM table_name;DECLARECONTINUEHANDLERFORNOT FOUND SET done =TRUE;OPEN cur;
read_loop: LOOPFETCH cur INTO col_name;IF done THENLEAVE read_loop;ENDIF;SET col_list = CONCAT(col_list,IF(col_list ='','',', '),'MAX(CASE WHEN ', pivot_col,' = ''', col_name,''' THEN ', value_col,' ELSE NULL END) AS `', col_name,'`');ENDLOOP;CLOSE cur;SET@sql= CONCAT('SELECT ', row_id,', ', col_list,' FROM ', table_name,' GROUP BY ', row_id,';');PREPARE stmt FROM@sql;EXECUTE stmt;DEALLOCATEPREPARE stmt;END//DELIMITER;-- 调用存储过程CALL dynamic_pivot('student_scores','id','subject','score');
4、详细测试demo
4.1、dataworks使用wm_concat函数和keyvalue实现行转列
-- 创建表createtableifnotexists school (`id` string,`obj_name` string,`obj_value` string
);-- 插入测试数据insertinto school
values('1','name','小明'),('1','age','12'),('2','name','小红'),('2','age','13');-- 列转行select id
,keyvalue(column_value,'name')as name
,keyvalue(column_value,'age')as age
from(select id
,wm_concat(';',concat(obj_name,':',obj_value))as column_value
from school
groupby id
);