问题描述
|
我正在尝试编写查询以创建数据的“表”,如下所示:
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\',NULL)) AS \'2011-04-21\',MAX(IF(c.`ProcessedOn` = \'2011-04-22\',NULL)) AS \'2011-04-22\',MAX(IF(c.`ProcessedOn` = \'2011-04-23\',NULL)) AS \'2011-04-23\',MAX(IF(c.`ProcessedOn` = \'2011-04-24\',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\',
变成更动态的内容(因为我的日期范围会改变)
解决方法
看看这个类似的线程,我在其中写了一个sp以完成任务
将两个表(具有1-M关系)联接在一起,其中第二个表需要“展平”到一行
编辑。更新的答案
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`,`percentchange`) values (2,\'2011-05-11\',22);
insert into `pivot`(`id`,`percentchange`) values (3,\'2011-05-12\',3);
insert into `pivot`(`id`,`percentchange`) values (4,7,4);
insert into `pivot`(`id`,`percentchange`) values (5,5);
insert into `pivot`(`id`,`percentchange`) values (6,12,6);
insert into `pivot`(`id`,`percentchange`) values (7,7);
insert into `pivot`(`id`,`percentchange`) values (8,\'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 `\",\"`,\");
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)