PHP Mysql group by date from accumulative values
I have a table with ID, value1, value2, value3 and tstamp (TIMESTAMP format) and i'm trying to group by each day and find a total for each day, however all values are accumulative, which poses a problem, because sum(value1) doesnt give the right output, this is my code:
$sql = "select date(tstamp), sum(".$column.") from mash group by date(tstamp) order by tstamp asc limit 10";
$result = mysql_query($sql);
$previous = 0;
$firstRun = true;
while($row = mysql_fetch_array($result))
{
$difference = $row[1] - $previous;
if (!$firstRun)
{
$strXML .= "<set name='".$row[0]."' value='".$difference."' color='AFD8F8' />";
}
$previous = $row[1];
$firstRun = false;
}
Can anyone spot the issue in this code, its not erroring, its just giving wrong answers.
EDIT:
To clear up any confusion, this is the SQL:
--------------------------------------------------------
--
-- Table structure for table `mash`
--
CREATE TABLE IF NOT EXISTS `mash` (
`id` int(25) NOT NULL AUTO_INCREMENT,
`steam` int(25) NOT NULL,
`bore_water` int(25) NOT NULL,
`boiler1oil` int(25) NOT NULL,
`boiler2oil` int(25) NOT NULL,
`tstamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5362 ;
--
-- Dumping data for table `mash`
--
INSERT INTO `mash` (`i开发者_如何学Pythond`, `steam`, `bore_water`, `boiler1oil`, `boiler2oil`, `tstamp`) VALUES
(2, 436, 73, 15, 1, '2010-11-25 12:28:03'),
(3, 495, 74, 36, 1, '2010-11-25 12:38:04'),
(4, 553, 76, 58, 1, '2010-11-25 12:48:09'),
(5, 565, 77, 74, 1, '2010-11-25 12:58:05'),
(6, 584, 79, 78, 1, '2010-11-25 13:08:05'),
(7, 630, 82, 100, 1, '2010-11-25 13:18:11'),
(8, 686, 86, 130, 1, '2010-11-25 13:28:07'),
(9, 740, 89, 151, 1, '2010-11-25 13:38:07'),
(10, 780, 93, 173, 1, '2010-11-25 13:48:13'),
(11, 883, 100, 218, 1, '2010-11-25 14:08:10');
Assuming I'm reading your table correctly, you're looking for the last entry of "value1" (or value2, etc.) which in-effect is the sum (judging by your mention of accumulative values)
+----+------+---------------------+
| id | val | tstamp |
+----+------+---------------------+
| 6 | 1 | 2010-01-02 01:00:00 |
| 7 | 4 | 2010-01-02 02:00:00 |
| 8 | 6 | 2010-01-02 03:00:00 |
| 9 | 15 | 2010-01-02 04:00:00 |
| 10 | 20 | 2010-01-02 05:00:00 | <-- this value
| 11 | 1 | 2010-01-03 01:00:00 |
| 12 | 4 | 2010-01-03 02:00:00 |
| 13 | 6 | 2010-01-03 03:00:00 |
| 14 | 15 | 2010-01-03 04:00:00 |
| 15 | 20 | 2010-01-03 05:00:00 | <- this value
| 1 | 2 | 2010-02-01 01:00:00 |
| 2 | 8 | 2010-02-01 02:00:00 |
| 3 | 16 | 2010-02-01 03:00:00 |
| 4 | 32 | 2010-02-01 04:00:00 |
| 5 | 64 | 2010-02-01 05:00:00 | <- this value
+----+------+---------------------+
Then you should be able to use MAX&DATE:
SELECT DATE(tstamp), MAX(val)
FROM mash
GROUP DATE(tstamp)
ORDER BY tstamp ASC;
Which will produce:
+--------------+----------+
| DATE(tstamp) | MAX(val) |
+--------------+----------+
| 2010-01-02 | 20 |
| 2010-01-03 | 20 |
| 2010-02-01 | 64 |
+--------------+----------+
If you are grouping by the date, it's going to group by the smallest increment of the date. You should be grouping by the day of the date. Something like:
select DATE_FORMAT(tstamp, '%Y-%m-%c') as ymd, sum(".$column.") from mash group by ymd order by tstamp asc limit 10
Which will give you a year-month-date format that it'll group on. If you need access to the year month and day values individually do:
select YEAR(tstamp) as year, MONTH(tstamp) as month, DAY(tstamp) as day, sum(".$column.") from mash group by year, month, day order by tstamp asc limit 10
The key part of your question is not the GROUP BY
portion, that will work just fine, it is what you mean by accumulative.
If you mean that a certain column tracks the total amount of rain in a year for each day (ie, the number keep going up because the delta between two records is the actual rain that occurred on that day) then what you need to do is first get rid of the delta. The SQL is going to be a bit hairy no matter how you do it, so you're probably better off doing it in PHP, but here is me trying with SQL.
create temporary table foo select * from bar;
create temporary table non_accumulative
select b.id, b.rain - f.rain as "rain", rain_timestamp from bar b join foo f on (f.id + 1) = b.id;
select sum(rain), date(rain_timestamp) from non_accumulative group by date(rain_timestamp) order by rain_timestamp;
Of course you can do the same with sub selects, but I find the temporary tables are faster.
精彩评论