一、列转行
mysql 数据库中,我们可能遇到将数据库中某一列的数据(多个值,按照英文逗号分隔),转化为多行数据(即一行转多行),然后join关联表,再转化为一行数据
如下目标数据,需要按照不同版本维护到表格里面,23-01这样的列名需要转换成对于的行的月份时间和对于的数值
car_code | market | version | display_version | category | subcategory | 23-01 | 23-02 | 23-03 | 23-04 | 23-05 | 23-06 | 23-07 | 23-08 | 23-08 | 23-10 | 23-11 | 23-12 | 2023 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ELE | CN | 2023-06 | 5+7 | manuf | NA | 0 | 79 | 391 | 149 | 155 | 389 | 203 | 337 | 298 | 1006 | 1263 | 1071 | 5341 |
ELE | CN | 2023-06 | 5+7 | stock | NA | 0 | 79 | 391 | 149 | 155 | 401 | 191 | 337 | 298 | 1006 | 1263 | 1071 | 5341 |
转化成这样的结果
car_code | market | version | display_version | category | subcategory | time_type | stat_time | goal_amount | etl_time |
---|---|---|---|---|---|---|---|---|---|
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-01 | 0 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-02 | 79 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-03 | 391 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-04 | 149 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-05 | 155 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-06 | 389 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-07 | 203 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-08 | 337 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-09 | 298 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-10 | 1006 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-11 | 1263 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | mth | 2023-12 | 1071 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | manuf | NA | year | 2023 | 5341 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-01 | 0 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-02 | 79 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-03 | 391 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-04 | 149 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-05 | 155 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-06 | 389 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-07 | 203 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-08 | 337 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-09 | 298 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-10 | 1006 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-11 | 1263 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | mth | 2023-12 | 1071 | 2023-08-30 |
ELE | CN | 2023-06 | 5+7 | stock | NA | year | 2023 | 5341 | 2023-08-30 |
二、实现方式
把上面行转列的数据放在另外一个视图里面,然后源头数据修改或者增加,视图可以直接看到数据变化。语句如下:
select
a.car_code as car_code,
a.market as market,
if(b.help_topic_id = 12,'year','mth') as time_type,#具体是月的目标还是年的目标
case when b.help_topic_id = 0 then '2023-01'
when b.help_topic_id = 1 then '2023-02'
when b.help_topic_id = 2 then '2023-03'
when b.help_topic_id = 3 then '2023-04'
when b.help_topic_id = 4 then '2023-05'
when b.help_topic_id = 5 then '2023-06'
when b.help_topic_id = 6 then '2023-07'
when b.help_topic_id = 7 then '2023-08'
when b.help_topic_id = 8 then '2023-09'
when b.help_topic_id = 9 then '2023-10'
when b.help_topic_id = 10 then '2023-11'
when b.help_topic_id = 11 then '2023-12'
when b.help_topic_id = 12 then '2023'
end as stat_time,#具体时间
a.category as category,#类别
a.subcategory as subcategory,#子类别
a.version as version,#版本,每个月版本可能不一样
SUBSTRING_INDEX(SUBSTRING_INDEX(a.goal_amount, '#', b.help_topic_id +1),'#',-1) as goal_amount,
CURRENT_TIMESTAMP as etl_time,#etl时间
a.display_version as display_version
from
(
select
car_code,
market,
version,
display_version,
category,
subcategory,
concat(`23-01` ,'#',`23-02`,'#',`23-03`,'#',`23-04`,'#',`23-05`,'#',`23-06`,'#',`23-07`,'#',`23-08` ,'#',`23-09`,'#',`23-10`,'#',`23-11`,'#',`23-12`,'#',`2023`) as goal_amount # 先把月目标数据拼接起来变成一个字段
from eboard_test.imp_eboard_mgt_plan_all
)a join mysql.help_topic b
where b.help_topic_id < ( LENGTH( a.goal_amount) - LENGTH(REPLACE ( a.goal_amount, '#', '' )) + 1 );
mysql.help_topic 的作用是对 SUBSTRING_INDEX 函数出来的数据(也就是按照分割符分割出来的)数据连接起来做笛卡尔积。如果 mysql.help_topic 没有权限,可以自己创建一张临时表,用来与要查询的表连接查询。
三、创建视图
create or replace
algorithm = UNDEFINED view `database_name`.`table_name` (
`car_code`,
`market`,
`time_type`,
`stat_time`,
`category`,
`subcategory`,
`version`,
`goal_amount`,
`etl_time`,
`display_version`
) as
select
a.car_code as car_code,
a.market as market,
if(b.help_topic_id = 12,'year','mth') as time_type,
case when b.help_topic_id = 0 then '2023-01'
when b.help_topic_id = 1 then '2023-02'
when b.help_topic_id = 2 then '2023-03'
when b.help_topic_id = 3 then '2023-04'
when b.help_topic_id = 4 then '2023-05'
when b.help_topic_id = 5 then '2023-06'
when b.help_topic_id = 6 then '2023-07'
when b.help_topic_id = 7 then '2023-08'
when b.help_topic_id = 8 then '2023-09'
when b.help_topic_id = 9 then '2023-10'
when b.help_topic_id = 10 then '2023-11'
when b.help_topic_id = 11 then '2023-12'
when b.help_topic_id = 12 then '2023'
end as stat_time,
a.category as category,
a.subcategory as subcategory,
a.version as version,
SUBSTRING_INDEX(SUBSTRING_INDEX(a.goal_amount, '#', b.help_topic_id +1),'#',-1) as goal_amount,
CURRENT_TIMESTAMP as etl_time,
a.display_version as display_version
from
(
select
car_code,
market,
version,
display_version,
category,
subcategory,
concat(`23-01` ,'#',`23-02`,'#',`23-03`,'#',`23-04`,'#',`23-05`,'#',`23-06`,'#',`23-07`,'#',`23-08`
,'#',`23-09`,'#',`23-10`,'#',`23-11`,'#',`23-12`,'#',`2023`) as goal_amount
from eboard_test.imp_eboard_mgt_plan_all
)a join mysql.help_topic b
where b.help_topic_id < ( LENGTH( a.goal_amount) - LENGTH(REPLACE ( a.goal_amount, '#', '' )) + 1 );```