动态列创建多年的mysql

时间:2016-03-31 02:42:54

标签: mysql

我为MYSQL编写了以下查询:

SELECT DATE_FORMAT(start, '%m/%e') as start,  (@total := @total + T.id) AS TotalApps, DATE_FORMAT(start, '%Y') as year FROM (SELECT start,COUNT(*) AS id FROM application WHERE start LIKE '2016%' GROUP BY MONTH(start), DAY(start)) AS T, (SELECT @total:=0) AS n

按预期输出表格,其中包含开始日期,累计申请数量和年份的列:

current table

我要做的是删除LIKE'2016%'以便我可以获取所有年份的数据并最终得到一个表格如下:

desired table

等等。

2 个答案:

答案 0 :(得分:1)

问题的累积性质使其与大多数其他枢轴问题完全不同。这是一种每年使用单独变量的方法:

SELECT DATE_FORMAT(start, '%m/%d') as mmdd, 
       (@t2016 := @t2016 + sum(year(start) = 2016)) as tot_2016,
       (@t2015 := @t2015 + sum(year(start) = 2015)) as tot_2015,
       (@t2014 := @t2014 + sum(year(start) = 2014)) as tot_2014
FROM application a CROSS JOIN
     (SELECT @t2016 := 0, @t2015 := 0, @t2014 := 0) params
GROUP BY DATE_FORMAT(start, '%m/%d')
ORDER BY mmdd;

编辑:

有时,group by和变量不能一起工作。这是使用子查询修复的:

SELECT mmdd,
       (@t2016 := @t2016 + cnt_2016) as tot_2016,
       (@t2015 := @t2015 + cnt_2015) as tot_2015,
       (@t2014 := @t2014 + cnt_2014) as tot_2014
FROM (SELECT DATE_FORMAT(start, '%m/%d') as mmdd, 
             sum(year(start) = 2016)) as cnt_2016,
             sum(year(start) = 2015)) as cnt_2015,
             sum(year(start) = 2014)) as cnt_2014
      FROM application a 
      GROUP BY DATE_FORMAT(start, '%m/%d')
      ORDER BY mmdd
     ) x CROSS JOIN
     (SELECT @t2016 := 0, @t2015 := 0, @t2014 := 0) params;

答案 1 :(得分:0)

这是一个完整的演示解决方案:

SELECT T2.month_day,
    IF (SUM(TotalApps * (YEAR(start) = '2016')) = 0, '', SUM(TotalApps * (YEAR(start) = '2016'))) as `2016`,
    IF (SUM(TotalApps * (YEAR(start) = '2015')) = 0, '', SUM(TotalApps * (YEAR(start) = '2015'))) as `2015`,
    IF (SUM(TotalApps * (YEAR(start) = '2014')) = 0, '', SUM(TotalApps * (YEAR(start) = '2014'))) as `2014`,
    IF (SUM(TotalApps * (YEAR(start) = '2013')) = 0, '', SUM(TotalApps * (YEAR(start) = '2013'))) as `2013`
FROM 
(    SELECT 
        start, month_day,
        IF(@last_year = YEAR(start),
           @total := @total + T.id,
           @total := T.id) AS TotalApps,
        @last_year := YEAR(start)
    FROM (SELECT start,COUNT(*) AS id, DATE_FORMAT(start, '%m/%e') as month_day
          FROM application 
          GROUP BY start
          ORDER BY start) AS T, (SELECT @total:=0, @last_year := NULL) AS n
) as T2 
GROUP BY month_day;

这是一个演示:

SQL:

-- data
create table application(start date);
insert into application values
('2016-01-01'),('2016-01-02'),('2016-01-02'),('2016-01-03'),
('2014-01-01'),('2014-01-02'),('2014-01-04'),
('2015-01-01'),('2015-01-02'),('2015-01-05');
select * from application;

-- query wanted
SELECT T2.month_day,
    IF (SUM(TotalApps * (YEAR(start) = '2016')) = 0, '', SUM(TotalApps * (YEAR(start) = '2016'))) as `2016`,
    IF (SUM(TotalApps * (YEAR(start) = '2015')) = 0, '', SUM(TotalApps * (YEAR(start) = '2015'))) as `2015`,
    IF (SUM(TotalApps * (YEAR(start) = '2014')) = 0, '', SUM(TotalApps * (YEAR(start) = '2014'))) as `2014`,
    IF (SUM(TotalApps * (YEAR(start) = '2013')) = 0, '', SUM(TotalApps * (YEAR(start) = '2013'))) as `2013`
FROM 
(    SELECT 
        start, month_day,
        IF(@last_year = YEAR(start),
           @total := @total + T.id,
           @total := T.id) AS TotalApps,
        @last_year := YEAR(start)
    FROM (SELECT start,COUNT(*) AS id, DATE_FORMAT(start, '%m/%e') as month_day
          FROM application 
          GROUP BY start
          ORDER BY start) AS T, (SELECT @total:=0, @last_year := NULL) AS n
) as T2 
GROUP BY month_day
;

输出:

mysql> select * from application;
+------------+
| start      |
+------------+
| 2016-01-01 |
| 2016-01-02 |
| 2016-01-02 |
| 2016-01-03 |
| 2014-01-01 |
| 2014-01-02 |
| 2014-01-04 |
| 2015-01-01 |
| 2015-01-02 |
| 2015-01-05 |
+------------+
10 rows in set (0.00 sec)

mysql> -- query wanted
mysql> SELECT T2.month_day,
    ->     IF (SUM(TotalApps * (YEAR(start) = '2016')) = 0, '', SUM(TotalApps * (YEAR(start) = '2016'))) as `2016`,
    ->     IF (SUM(TotalApps * (YEAR(start) = '2015')) = 0, '', SUM(TotalApps * (YEAR(start) = '2015'))) as `2015`,
    ->     IF (SUM(TotalApps * (YEAR(start) = '2014')) = 0, '', SUM(TotalApps * (YEAR(start) = '2014'))) as `2014`,
    ->     IF (SUM(TotalApps * (YEAR(start) = '2013')) = 0, '', SUM(TotalApps * (YEAR(start) = '2013'))) as `2013`
    -> FROM
    -> (    SELECT
    ->         start, month_day,
    ->         IF(@last_year = YEAR(start),
    ->            @total := @total + T.id,
    ->            @total := T.id) AS TotalApps,
    ->         @last_year := YEAR(start)
    ->     FROM (SELECT start,COUNT(*) AS id, DATE_FORMAT(start, '%m/%e') as month_day
    ->           FROM application
    ->           GROUP BY start
    ->           ORDER BY start) AS T, (SELECT @total:=0, @last_year := NULL) AS n
    -> ) as T2
    -> GROUP BY month_day
    -> ;
+-----------+------+------+------+------+
| month_day | 2016 | 2015 | 2014 | 2013 |
+-----------+------+------+------+------+
| 01/1      | 1    | 1    | 1    |      |
| 01/2      | 3    | 2    | 2    |      |
| 01/3      | 4    |      |      |      |
| 01/4      |      |      | 3    |      |
| 01/5      |      | 3    |      |      |
+-----------+------+------+------+------+
5 rows in set (0.00 sec)