合并MySQL中的列

时间:2014-01-13 21:53:58

标签: php mysql database primary-key

我正在尝试在我的数据库中逐年查看模式。我的数据库是MySQL,我的服务器端语言是PHP,数据可视化器是Morris.js

我已经逐年导出了我的数据,并且一直在尝试使用PHP合并这些数据,但效率的顺序很糟糕且不直观,所以我希望在MySQL中合并列,而不是在PHP中合并

我正在提取数据,以便每年1月7日代表Jan 1 + Jan 2 + .. + Jan 7,12月31代表Jan 1 + .. + Mar 25 + .. + Dec 31。这一切都在一年之内,因此2012年专栏仅在2012年累积。

对于2014年,数据看起来像,

+--------+-------+
| date   | books |
+--------+-------+
| Jan-01 |    17 |
| Jan-02 |    40 |
| Jan-03 |    99 |
| Jan-04 |   164 |
| Jan-05 |   307 |
| Jan-06 |   527 |
| Jan-07 |   744 |
| Jan-08 |   866 |
| Jan-09 |   941 |
| Jan-10 |   990 |
| Jan-11 |  1016 |
| Jan-12 |  1030 |
| Jan-13 |  1082 |
+--------+-------+

现在我正在提取数据,

<?php

// the actual code includes data for 2010-2014

$sql2014Cumulative = "SELECT DATE_FORMAT(b.`date_added`, '%b-%d') AS date, COUNT(*) AS books\n"
    . "FROM (SELECT DISTINCT date(`date_added`) `date_added` FROM `books` WHERE YEAR(`date_added`) = 2014) b\n"
    . "JOIN `books` b2 ON b.`date_added` >= date(b2.`date_added`)\n"
    . "WHERE YEAR(b2.`date_added`) = 2014\n"
    . "GROUP BY b.`date_added`\n"
    . "ORDER BY b.`date_added` ASC";

$sql2013Cumulative = "SELECT DATE_FORMAT(b.`date_added`, '%b-%d') AS date, COUNT(*) AS books\n"
    . "FROM (SELECT DISTINCT date(`date_added`) `date_added` FROM `books` WHERE YEAR(`date_added`) = 2013) b\n"
    . "JOIN `books` b2 ON b.`date_added` >= date(b2.`date_added`)\n"
    . "WHERE YEAR(b2.`date_added`) = 2013\n"
    . "GROUP BY b.`date_added`\n"
    . "ORDER BY b.`date_added` ASC";

$result2014Cumulative = $mysqli->query($sql2014Cumulative);
$result2013Cumulative = $mysqli->query($sql2013Cumulative);

while($row2014Cumulative = $result2014Cumulative->fetch_array(MYSQLI_ASSOC))
{
    $rows2014Cumulative[] = array('date' => $row2014Cumulative['date'], '2014' => $row2014Cumulative['books']);
}

while($row2013Cumulative = $result2013Cumulative->fetch_array(MYSQLI_ASSOC))
{
    $rows2013Cumulative[] = array('date' => $row2013Cumulative['date'], '2013' => $row2013Cumulative['books']);
}

$mergedDataCumulative = array_replace_recursive($rows2013Cumulative, $rows2014Cumulative);

?>

<script>var booksYearOverYearCumulative = <?php echo json_encode($mergedDataCumulative); ?>;</script>

...

在看起来像这样的架构上

+---------------+------------------+------+-----+---------------------+-----------------------------+
| Field         | Type             | Null | Key | Default             | Extra                       |
+---------------+------------------+------+-----+---------------------+-----------------------------+
| id            | int(10) unsigned | NO   | PRI | NULL                | auto_increment              |
| user_id       | int(10) unsigned | NO   | MUL | NULL                |                             |
| course_code   | varchar(9)       | NO   |     | NULL                |                             |
| for_sale      | tinyint(1)       | NO   |     | NULL                |                             |
| date_added    | datetime         | NO   |     | NULL                |                             |
| date_removed  | datetime         | NO   |     | 0000-00-00 00:00:00 |                             |
| date_modified | timestamp        | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
+---------------+------------------+------+-----+---------------------+-----------------------------+

然后我从每年获取每组数据并将它们合并到一个数组中并导出为Morris.js的JSON。这是一个单调乏味的部分。

如果这一切都在MySQL中完成并且数据导出到一个表中并且显示为这样,那么更容易的是,

+--------+-------+-------+-------+
| date   | 2014  | 2013  | 2012  |
+--------+-------+-------+-------+
| Jan-01 |    17 |    12 |     0 |
| Jan-02 |    40 |    40 |    12 |
| Jan-03 |    99 |   102 |    18 |
| Jan-04 |   164 |   136 |    27 |
| Jan-05 |   307 |   144 |    45 |
| Jan-06 |   527 |   504 |    48 |
| Jan-07 |   744 |   893 |   189 |
| Jan-08 |   866 |  1002 |   567 |
| Jan-09 |   941 |  1100 |   890 |
| Jan-10 |   990 |  1430 |  1054 |
| Jan-11 |  1016 |  1435 |  1278 |
| Jan-12 |  1030 |  1545 |  1575 |
| Jan-13 |  1082 |  1604 |  1897 |
+--------+-------+-------+-------+

因此,有没有人知道如何在每年内将累积数据分组并将其导出到一个表中,而不是使用PHP合并所有数据?

2 个答案:

答案 0 :(得分:2)

简单的情况

select 
  b.date 'date',
  sum(b.y2014) '2014', 
  sum(b.y2013) '2013', 
  sum(b.y2012) '2012'
from (
  select
   date_format(date_added, '%b-%d') as 'date',
   case year(date_added) when 2014 then books else 0 end as 'y2014',
   case year(date_added) when 2013 then books else 0 end as 'y2013',
   case year(date_added) when 2012 then books else 0 end as 'y2012'
  from books 
) b
group by b.date;

加入

select
  date_format(y14.date_added, '%b-%d') as 'date', 
  y14.books as '2014',
  y13.books as '2013',
  y12.books as '2012'
from 
  books y14
  left join books y13
     on   year(y13.date_added) = 2013
     and  month(y13.date_added) = month(y14.date_added)
     and  day(y13.date_added)   = day(y14.date_added)
  left join books y12
     on   year(y12.date_added) = 2012
     and  month(y12.date_added) = month(y14.date_added)
     and  day(y12.date_added)   = day(y14.date_added)
where
  year(y14.date_added) = 2014
;

你可以使用许多不同的方式,结合所有等等......

SQLFIDDLE

result

SQLFIDDLE

答案 1 :(得分:1)

这是您的查询,清理为SQL:

SELECT DATE_FORMAT(b.`date_added`, '%b-%d') AS date, COUNT(*) AS books
FROM (SELECT DISTINCT date(`date_added`) `date_added`
      FROM `books`
      WHERE YEAR(`date_added`) = 2014
     ) b JOIN
     `books` b2
     ON b.`date_added` >= date(b2.`date_added`)
WHERE YEAR(b2.`date_added`) = 2014
GROUP BY b.`date_added`
ORDER BY b.`date_added` ASC;

让我们修改它来处理多年。我认为这样做:

SELECT DATE_FORMAT(b.`date_added`, '%b-%d') AS date,
       sum(b.yr = 2014) AS books_2014,
       sum(b.yr = 2013) AS books_2013,
       sum(b.yr = 2012) AS books_2012
FROM (SELECT DISTINCT date(`date_added`) as date_added, year(date_added) as yr
      FROM `books`
     ) b JOIN
     `books` b2
     ON b.`date_added` >= date(b2.`date_added`) and
        b.yr = year(b2.date_added)
GROUP BY DATE_FORMAT(b.`date_added`, '%b-%d')
ORDER BY `date` ASC;