行转列

Posted 张侦毅

tags:

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

文章目录

使用场景

  有时我们在进行图表数据统计时,在图表中,横轴为月份(英文大写),纵轴为图表数据。但是我们所使用的数据源表结构如下面的数据源所示,而此时,下面的一条数据,其实就需要我们将其行转列,进行格式化,然后将数据显示在图表中。

  当然,我们可以通过存储过程方法解决该问题,但是此处我并不推荐使用存储过程,因为由于业务的复杂性,我们在其它地方也可能会用到行转列后的数据的连表查询操作,而如果我们使用存储过程,这就意味着我们并不能再使用连表查询操作来处理存储过程了,而如果要在其它地方,仍然能够对行转列后的数据进行连表查询操作,这里我推荐使用视图方法。

数据源

  建表语句如下:

CREATE TABLE `dept_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `name` varchar(64) DEFAULT NULL COMMENT '部门',
  `year` int(10) DEFAULT NULL COMMENT '年份',
  `month_1` double DEFAULT NULL COMMENT '一月数据',
  `month_2` double DEFAULT NULL COMMENT '二月数据',
  `month_3` double DEFAULT NULL COMMENT '三月数据',
  `month_4` double DEFAULT NULL COMMENT '四月数据',
  `month_5` double DEFAULT NULL COMMENT '五月数据',
  `month_6` double DEFAULT NULL COMMENT '六月数据',
  `month_7` double DEFAULT NULL COMMENT '七月数据',
  `month_8` double DEFAULT NULL COMMENT '八月数据',
  `month_9` double DEFAULT NULL COMMENT '九月数据',
  `month_10` double DEFAULT NULL COMMENT '十月数据',
  `month_11` double DEFAULT NULL COMMENT '十一月数据',
  `month_12` double DEFAULT NULL COMMENT '十二月数据',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

  在表中插入数据:

insert  into `dept_data`(`id`,`name`,`year`,`month_1`,`month_2`,`month_3`,`month_4`,`month_5`,`month_6`,`month_7`,`month_8`,`month_9`,`month_10`,`month_11`,`month_12`) values (1,'部门1',2017,1,2,3,4,5,6,7,8,9,10,11,12),(2,'部门2',2018,1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1,11.11,12.12);

行转列

创建个月视图

  创建一月份视图:

CREATE VIEW dept_data_month_01_view AS 
SELECT 
  dd.`id`,
  1 AS month_index,
  dd.`name`,
  STR_TO_DATE(CONCAT(dd.`year`, '-01'), '%Y-%m') AS DATE,
  dd.year,
  dd.`month_1` AS DATA 
FROM
  dept_data dd;

   创建二月份视图

CREATE VIEW dept_data_month_02_view AS 
SELECT 
  dd.`id`,
  2 AS month_index,
  dd.`name`,
  STR_TO_DATE(CONCAT(dd.`year`, '-02'), '%Y-%m') AS DATE,
  dd.year,
  dd.`month_2` AS DATA 
FROM
  dept_data dd;

   以此类推,创建各月视图,在这里,我就不一一展示其创建视图语句了。

将个月视图拼接成完整月度数据视图

   当我们将所有月份的视图创建完成后,再将各月的视图拼接成一个完整的月度数据视图,其完整月度数据视图创建语句如下:

CREATE VIEW dept_data_month_view AS
SELECT * FROM dept_data_month_01_view
UNION ALL
SELECT * FROM dept_data_month_02_view
UNION ALL
SELECT * FROM dept_data_month_03_view
UNION ALL
SELECT * FROM dept_data_month_04_view
UNION ALL
SELECT * FROM dept_data_month_05_view
UNION ALL
SELECT * FROM dept_data_month_06_view
UNION ALL
SELECT * FROM dept_data_month_07_view
UNION ALL
SELECT * FROM dept_data_month_08_view
UNION ALL
SELECT * FROM dept_data_month_09_view
UNION ALL
SELECT * FROM dept_data_month_10_view
UNION ALL
SELECT * FROM dept_data_month_11_view
UNION ALL
SELECT * FROM dept_data_month_12_view

将完整月度数据视图进行格式化

   由于我们最终是要将其展示在图表中的,而在图表中,横轴是大写的英文月份,因而我们又需要将行转列后的数据执行格式化操作。

CREATE VIEW dept_data_month_format_view AS
SELECT 
ddmv.`id`,
ddmv.`month_index`,
ddmv.`name`,
ddmv.`year`,
ddmv.`DATE`,
CASE
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 01 
    THEN 'Jan' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 02 
    THEN 'Feb' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 03 
    THEN 'Mar' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 04 
    THEN 'Apr' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 05 
    THEN 'May' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 06 
    THEN 'Jun' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 07 
    THEN 'Jul' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 08 
    THEN 'Aug' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 09 
    THEN 'Sep' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 10 
    THEN 'Oct' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 11 
    THEN 'Nov' 
    WHEN DATE_FORMAT(ddmv.`date`, '%m') = 12 
    THEN 'Dec' 
  END month_format,
ddmv.`DATA`
FROM dept_data_month_view ddmv ORDER BY ddmv.`month_index` ASC

图表展示效果

   最终在图表中的展示效果(2018年):

计算月度平均值

创建月度数据平均值视图

   而如果我们要统计每个月的平均值,如下:

月份平均值
一月1月份数据除以1
二月1、2月份数据之和除以2
三月1、2、3月份数据之和除以3

   此时,月度数据平均值视图创建语句如下:

CREATE VIEW dept_data_month_format_target_view AS 
SELECT 
  ddmfv.`id`,
  ddmfv.`month_index`,
  ddmfv.`name`,
  ddmfv.`year`,
  ddmfv.`DATE`,
  ddmfv.`month_format`,
  (SELECT 
    SUM(ddmfv2.DATA) 
  FROM
    dept_data_month_format_view ddmfv2 
  WHERE ddmfv2.DATE <= ddmfv.`DATE` 
    AND ddmfv2.name = ddmfv.`name`) / ddmfv.`month_index` month_average 
FROM
  dept_data_month_format_view ddmfv 
ORDER BY ddmfv.month_index ASC 

图表展示效果

  结合图表一中的数据,其最终的展示结果如下:

  当我们将鼠标指针指上去时,我们可以看到当前月份所展示的数据值:

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

MySQL 行转列 -》动态行转列 -》动态行转列带计算

MySQL行转列与列转行

PIVOT:行转列函数

SQLSERVER有张表,需要每晚自动实现行转列。

Hive 行转列 & 列转行

oracle行转列sql怎么写?