Reputation: 1405
I have a MySQL/MariaDB database which includes timestamps created with the PHP function date()
.
Like this:
ID | Name | Date
--------------------------
12 | John | 123456789
13 | Mike | 987654321
...
29 | Rick | 123498765
30 | Adam | 987651234
Now I need to get the count of all persons per month based in the last 12 months since the current one.
Example:
Currently is March, so I need to get something like this:
March has 3 persons
February has 14 persons
January has 16 persons
December has 13
November has 16
October has 30
...
And goes on.
How can I do this with PHP?
So far I have this simple for
loop which returns last 12 months and then the timestamp for each, but I don't really know how to compare the returned timestamp with the DB timestamp.
for ($number = 0; $number <= 11; $number++) {
$month = strtotime("-".$number." month");
echo "Timestamp: ".$month."<br>";
echo "Month: ".date("F", $month);
echo "<hr>";
};
That loop returns something like this:
Timestamp: 1488398035
Month: March
---
Timestamp: 1485978835
Month: February
---
Timestamp: 1483300435
Month: January
---
Timestamp: 1480622035
Month: December
---
Timestamp: 1478026435
Month: November
---
Timestamp: 1475348035
Month: October
---
Timestamp: 1472756035
Month: September
---
Timestamp: 1470077635
Month: August
---
Timestamp: 1467399235
Month: July
---
Timestamp: 1464807235
Month: June
---
Timestamp: 1462128835
Month: May
---
Timestamp: 1459536835
Month: April
Upvotes: 0
Views: 1864
Reputation: 5371
You can do this in MySQL, simply sub table_name
for the actual name of your table:
SELECT
YEAR(FROM_UNIXTIME(`Date`)),
MONTH(FROM_UNIXTIME(`Date`)),
count(*) as total
FROM table_name
WHERE `Date` > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 12 month))
GROUP BY YEAR(FROM_UNIXTIME(`Date`)), MONTH(FROM_UNIXTIME(`Date`))
Generally this concept is more efficient (especially once you have large amounts of data) if you you use a datetime column instead. This will work though. This query also assumes 12 months ago literally, to the day, you could calculate the exact timestamp of the first day of the month and etc... Again, this would be way easier and more efficient with a datetime column.
Upvotes: 1
Reputation: 2254
Try this
SELECT
YEAR(FROM_UNIXTIME(`Date`)),
MONTH(FROM_UNIXTIME(`Date`)),
count(*) as total
FROM table_name
WHERE date(from_unixtime(`Date`))
BETWEEN CURDATE() AND CURDATE() + INTERVAL 12 MONTH;
Upvotes: 0
Reputation: 108430
To return twelve rows, one for the current month, and eleven for the preceding months, along with a count (even when the count is zero), we can do something like this:
SELECT CONCAT(DATE_FORMAT(r.sd,'%M is ')
,COUNT(t.name)
,' person'
,IF(COUNT(t.name)=1,'','s')
) AS `something_like_this`
FROM ( SELECT d.d - INTERVAL i.i - 0 MONTH AS sd
, d.d - INTERVAL i.i - 1 MONTH AS ed
FROM ( SELECT DATE_FORMAT(NOW(),'%Y-%m-01') AS d ) d
CROSS
JOIN ( SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
UNION ALL SELECT 10 UNION ALL SELECT 11
) i
ORDER BY sd DESC
) r
LEFT
JOIN mytable t
ON t.date >= UNIX_TIMESTAMP(r.sd)
AND t.date < UNIX_TIMESTAMP(r.ed)
GROUP BY r.sd
ORDER BY r.sd DESC
The inline view r
is designed to return 12 rows. On those rows, we return the start and end date of the period. In this case, the first day of the month, and the first day of the following month.
An outer join to the table we want to get a count of rows from. Given that the date
column is stored as a unix style 32-bit integer (seconds since epoch), we can use the MySQL UNIX_TIMESTAMP function to convert the MySQL DATE
values (from r
), so we have values we can compare.
To answer the question that was asked, yes, it's also possible to achieve this type of functionality in PHP.
With the current code that generates the "beginning" timestamp for the period, also generate the "ending" timestamp (the first of the following month.)
Then execute a query that gets a count.
SELECT COUNT(t.name) AS cnt
FROM mytable t
WHERE t.date >= 1488326400 /* 2017-03-01 00:00 UTC */
AND t.date < 1491004800 /* 2017-04-01 00:00 UTC */
Fetch the result, and output a line. For the previous month, run another query
SELECT COUNT(t.name) cnt
FROM mytable t
WHERE t.date >= 1485907200 /* 2017-02-01 00:00 UTC */
AND t.date < 1488326400 /* 2017-03-01 00:00 UTC */
Fetch the result, output a line. And repeat.
Upvotes: 0
Reputation: 30819
You can use FROM_UNIXTIME
and DATE_FORMAT
functions to convert timestamp into date and date into string respectively, and get the counts, e.g.:
SELECT DATE_FORMAT(FROM_UNIXTIME(`date`), '%Y-%m') as `month`, COUNT(ID) as count
FROM table
GROUP BY `month`;
Upvotes: 0