ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL数据透视表,包含基于单列数据的动态标头

2019-09-27 16:14:17  阅读:194  来源: 互联网

标签:mysql pivot-table dynamic


我正在尝试编写一个查询来创建数据的“表”,如下所示:

SELECT cs.`category_id`, cs.`ProcessDate`, cs.`PercentChange`
  FROM `Category_Statistics` cs
 WHERE cs.`ProcessDate` >= '2011-05-10'
   AND cs.`ProcessDate` <= '2011-05-14'

哪个会返回类似的东西:

CategoryId  |  ProcessDate  | PercentChange
-------------------------------------------
category_4  |  2011-05-10   |      10
category_4  |  2011-05-11   |      18
category_4  |  2011-05012   |      12
...
category_7  |  2011-05-10   |      21
category_7  |  2011-05-11   |      7
...
category_12 |  2011-05-10   |      7
category_12 |  2011-05-11   |      15

现在我希望结果是这样的(来自MySQL查询,不受应用程序操纵):

CategoryId    | 2011-05-10 | 2011-05-11 | 2011-05-12 | 2011-05-13 | 2011-05-14 |
--------------------------------------------------------------------------------
category_4    |     10     |     18     |     12     |      9     |      14    |
category_7    |     21     |      7     |     16     |      14    |      13    |
categeory_12  |      7     |     15     |     11     |      19    |       8    |
--------------------------------------------------------------------------------

这有两点需要注意:

>日期范围可以增长或缩小
(取决于查询)
> PercentChange在某些情况下可能为null
案例(比如category_7 /
2011-05-12可能没有设定价值)

所以最终我不太确定如何构建查询的选择部分以反映动态数量的列(我知道它与CONCAT有关).

编辑 – >部分工作代码 – >

SELECT `CategoryId`,
   MAX(IF(c.`ProcessedOn` = '2011-04-20', c.`PercentChange`, NULL)) AS '2011-04-20',
   MAX(IF(c.`ProcessedOn` = '2011-04-21', c.`PercentChange`, NULL)) AS '2011-04-21',
   MAX(IF(c.`ProcessedOn` = '2011-04-22', c.`PercentChange`, NULL)) AS '2011-04-22',
   MAX(IF(c.`ProcessedOn` = '2011-04-23', c.`PercentChange`, NULL)) AS '2011-04-23',
   MAX(IF(c.`ProcessedOn` = '2011-04-24', c.`PercentChange`, NULL)) AS '2011-04-24'
  FROM `Category_Gravity` c
 WHERE c.`ProcessedOn` >= '2011-04-20'
   AND c.`ProcessedOn` <= '2011-04-24'
 GROUP BY `CategoryId`

我现在要做的就是转

MAX(IF(c.`ProcessedOn` = '2011-04-20', c.`PercentChange`, NULL)) AS '2011-04-20',

变得更有活力(因为我的日期范围会改变)

解决方法:

看看这个类似的线程,我写了一个sp来完成任务

Join two tables (with a 1-M relationship) where the second table needs to be ‘flattened’ into one row

编辑.更新的答案

create table `pivot` (
  `id` int(11) not null auto_increment,
  `categoryid` int(11) default null,
  `processdate` date default null,
  `percentchange` int(11) default null,
  primary key (`id`)
) engine=myisam auto_increment=9 default charset=latin1;

/*Data for the table `pivot` */

insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (1,4,'2011-05-10',1);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (2,4,'2011-05-11',22);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (3,4,'2011-05-12',3);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (4,7,'2011-05-10',4);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (5,7,'2011-05-11',5);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (6,12,'2011-05-10',6);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (7,12,'2011-05-12',7);
insert  into `pivot`(`id`,`categoryid`,`processdate`,`percentchange`) values (8,4,'2011-05-13',12);



delimiter //
drop procedure if exists dynamic_view2//
create procedure dynamic_view2(in sdate date,in edate date)
begin
declare finish int default 0;
declare cdate date;
declare str varchar(10000) default "select categoryid,";
declare curs cursor for select processdate from pivot where processdate between sdate and edate group by processdate;
declare continue handler for not found set finish = 1;
open curs;
my_loop:loop
fetch curs into cdate;
if finish = 1 then
leave my_loop;
end if;
set str = concat(str, "max(case when processdate = '",cdate,"' then percentchange else null end) as `",cdate,"`,");
end loop;
close curs;
set str = substr(str,1,char_length(str)-1);
set @str = concat(str," from pivot
            group by categoryid");

prepare stmt from @str;
execute stmt;
deallocate prepare stmt;
end;//
delimiter ;


mysql> call dynamic_view2('2011-05-10','2011-05-13');
+------------+------------+------------+------------+------------+
| categoryid | 2011-05-10 | 2011-05-11 | 2011-05-12 | 2011-05-13 |
+------------+------------+------------+------------+------------+
|          4 |          1 |         22 |          3 |         12 |
|          7 |          4 |          5 |       NULL |       NULL |
|         12 |          6 |       NULL |          7 |       NULL |
+------------+------------+------------+------------+------------+
3 rows in set (0.00 sec)

标签:mysql,pivot-table,dynamic
来源: https://codeday.me/bug/20190927/1824002.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有