我正在尝试在我的数据库中逐年查看模式。我的数据库是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合并所有数据?
答案 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
;
你可以使用许多不同的方式,结合所有等等......
答案 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;