mysql的动态列创建

mysql的动态列创建,mysql,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

我已经为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
它按预期输出表格,其中包含一列开始日期、累计申请数量和年份:

我想做的是删除类似“2016%”的数据,这样我就可以得到所有年份的数据,最后得到一个如下表:


等等。

这个问题的累积性质使得它与大多数其他关键问题截然不同。以下是一种每年使用单独变量的方法:

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;
编辑:

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

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;

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

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: 输出:
这个问题可能是其他问题的重复,但不是原来的问题。这是在列中要求累计金额。谢谢,有没有一种方法可以在我不必每年手动编码的情况下完成它?它将自动调用“添加多年的行”?@StevenStangle。这需要动态SQL,而且会更加复杂,因为pivot的累积求和特性。实际上我运行了它,它也没有进行求和。我想这些可能是一天的计数,不是正确的累积。那很好,这将在PHP中,所以我可以写一个循环来生成年份,但累积部分是关闭的。
-- 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)