I am trying to get a COUNT of the last 12 months of appointments grouped by month for output into a chart. The following works fine but I need it to return 0 if no results for each month.
$query = "SELECT COUNT(id) as total_month FROM appointments WHERE created >= DATE(NOW()) - INTERVAL 365 DAY GROUP BY Month(created)";
$query = $mysqli->real_escape_string($query);
if($result = $mysqli->query($query)){
while($row = $result->fetch_array())
{
$month_total_appointments .= $row['total_month'].',';
}
}
echo $month_total_appointments;
================================================================
Simple table structure and example for appointments Table
id customer_name created
1 John 2020-05-01 08:00:00 <= stored as datetime
2 Mike 2020-04-01 09:00:00
3 Steve 2020-02-01 10:00:00
Output would be 0,0,0,0,0,0,0,0,1,0,1,1
======================================================
Current output is: 1,1,1
I've read some use a month table and LEFT JOIN but everything i've tried doesn't seem to work. Can anyone help please?
You won't get zeroes for rows that aren't there. Grouping combines rows that match particular criteria, but it can't fabricate them out of nothing.
That's why it's typical to include the grouping criteria in the results:
SELECT COUNT(id), MONTH(created) AS created_month
FROM appointments
WHERE created >= DATE(NOW()) - INTERVAL 365 DAY
GROUP BY created_month
Then you can expand that in your application code to fill in the missing values. The alternative is you need a fully populated list of all possible dates to JOIN against.
Keep in mind the MONTH() thing will wrap around and group January 2020 with January 2021. You may want to split this up:
SELECT COUNT(id), YEAR(created) AS created_year, MONTH(created) AS created_month
FROM appointments
WHERE created >= DATE(NOW()) - INTERVAL 365 DAY
GROUP BY created_year, created_month
Related
I have a MySQL DB where I store dates in the following format
2017-04-03
I need to split or search dates to get all dates and records for January, Feb, March and so on in between all the dates I have in DB
$result = mysql_query("SELECT * FROM lbs_trace_etrack WHERE MONTH(lbs_date) = MONTH(CURDATE()) AND YEAR(lbs_date) = YEAR(CURDATE()) ORDER BY lbs_date DESC, lbs_time DESC");
I use the above query to search Current month and year. I am drawing up a graph that shows me stats from each month this is the reason I want each months count
I need to place the counts for the search in the following format.
var seriesData = [{
name: 'Hijackings',
data: [Value Jan, Value Feb, Value March, and all the other months ]
}, {
If anyone can just help me with the filter on each month query would help me greatly
Try this query:
select count(*) as total, MONTH(lbs_date) as track_month, YEAR(lbs_date) as track_year
FROM lbs_trace_stack t
GROUP BY track_year, track_month
Or if you only want month or only want year, you have just to remove
MONTH(lbs_date) and track_month --> if you want to see the year remove this
YEAR(lbs_date) and track_year --> if you want to see the month remove this
from the select part and group by part.
In addiction, if you want to filter on one or more months you can of course use the where statement, to set up your filter.
There are a several ways to write some where condition that do the same things, for example:
SELECT COUNT(*) as total, MONTH(lbs_date) as track_month
FROM lbs_trace_stack t
-- WHERE track_month = 2 -> February
-- WHERE track_month > 2 -> Form March
-- WHERE track_month = 2 OR track_month = 3 -> February or March
-- WHERE MONTHNAME(lbs_date)='February' --> if you want to use month name
GROUP BY track_month
I have found that this query works
$query = "SELECT rep_date FROM `bureau` WHERE MONTH(rep_date) = 1 AND type = 'Overdue'";
$result = mysql_query($query);
echo " ".mysql_num_rows($result)." "
?>
<?php
while($rows=mysql_fetch_array($result)){
?>
Using the MONTH(rep_date)=1 will filter all January changing 1 to 2 will do Feb and so on
I want to list the scores, by month, for something that happened over the last 12 months. I noticed my query below was combining the results of the first partial month with the results of the last partial month. That is, my July report combined July 9-31, 2015 with July 1-8 2016 (now is July 8). I only want the latest month to represent the latest year. Here is what I was using...
$query = "SELECT record_id,
time_scored,
MONTH(time_scored) as month_added,
score, comment
FROM records
WHERE score IS NOT NULL AND
time_scored >= DATE_SUB(curdate(),INTERVAL 12 MONTH)
ORDER BY time_scored DESC";
Any help would be appreciated. Thanks!
Subtract 12 months from next months 1st day
$query = "SELECT record_id,
time_scored,
MONTH(time_scored) as month_added,
score, comment
FROM records
WHERE score IS NOT NULL AND
time_scored >= DATE_SUB(DATE_ADD(subdate(curdate(), (day(curdate())-1)), INTERVAL 1 MONTH),INTERVAL 12 MONTH)
ORDER BY time_scored DESC";
I would like the database to count how many reports were generated for last month only and not from the current date backwards a month as it currently is e.g. 16/08/15 to 16/08/15. For example, I would like it to only count the total for August 2015, then once it is October, count the data for September 2015, so you can look back at the previous month how many reports were generated in the database.
I hope that makes sense? It will be used to count how many reports an employee has created to work out commission.
<?php
if ($result = $mysqli->query("SELECT count(inventory_id) cc FROM inventories WHERE inventory_date > CURRENT_DATE() - INTERVAL 1 MONTH")) {
$row = $result->fetch_assoc();
printf("<div class='col-6 statsMonth inventoryMonthStats'>Inventories in 30 days <span class='statCircle'>%d</span></div>", $row['cc']);
$result->close();
}
?>
Gets a bit ugly, but... assuming you always want "previous" month:
SELECT ...
...
WHERE YEAR(inventory_date) = YEAR(now() - interval 1 month)
AND MONTH(inventory_date) = MONTH(now() - interval 1 month)
If you want arbitrary previous months, then swap now() for a date in the month you want to calculate the "previous" of.
Say I've got a simple mysql table with columns id, title, date. Each day can have several rows, but not every day has a row. For example there might be 5 rows with June 15th as the date, but zero rows with June 14th as the date. How can I get all results from the past 7 days, excluding June 14th because it has no rows. So I'm not just subtracting 7 days from the current date. I want to get only the past 7 days which have any rows at all.
Then I want to return each day as a single result, like a group by date, but by the year/month/day part of the timestamp, so that what I get back is only 7 results, and each result is like an array of individual rows.
I hope that makes sense. Any ideas?
Edit:
I realized I can do it something like this:
WHERE Date BETWEEN DATE_SUB( NOW(), INTERVAL DATEDIFF( NOW(), (SELECT Date FROM test GROUP BY Date LIMIT 7,1 ) ) DAY ) and NOW()
But this gives an SQL syntax error. What I'm trying to do is a subquery and group by date to get one result for each day, and return one result starting at offset 7, then do a DATEDIFF on that to get the number of days that DATE_SUB should put in the INTERVAL x DAYS
You won't be able to get the same day results back as an array, but you can group it by date, with the titles comma separated:
SELECT GROUP_CONCAT(title) AS titles, date
FROM test
WHERE date > DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY date;
Then in PHP, do something like this:
foreach ($results as $row)
{
echo $row['date'];
foreach ($row['titles'] as $title)
{
echo $title;
}
}
Figured it out: It works!
WHERE Date BETWEEN DATE_SUB(NOW(), INTERVAL (DATEDIFF( NOW(), (SELECT Date FROM test GROUP BY Date ORDER BY Date DESC LIMIT 8,1 ) ) ) DAY) and NOW()
I was missing a parentheses, and I had to add ORDER BY and DESC to the subquery.
I have a fun one for you. I have a database with the date columns free_from and free_until. What I need to find is the amount of days between now and 1 month today which are free. For example, if the current date was 2013/01/15 and the columns were as follows:
free_from | free_until
2013/01/12| 2013/01/17
2013/01/22| 2013/01/26
2013/01/29| 2013/02/04
2013/02/09| 2013/02/11
2013/02/14| 2013/02/17
2013/02/19| 2013/02/30
The answer would be 16
as 2 + 4 + 6 + 2 + 2 + 0 = 16
The first row only starts counting at the 15th rather than the 12th
since the 15th is the current date.
The last row is discounted because none of the dates are within a
month of the current date.
The dates must be counted as it the free_from date is inclusive and
the free_until date is exclusive.
I'm assuming DATEDIFF() will be used somewhere along the line, but I can't, for the life of me, work this one out.
Thanks for your time!
Edit: This is going into PHP mysql_query so that might restrict you a little concerning what you can do with MYSQL.
SET #today = "2013-01-15";
SET #nextm = DATE_ADD(#today, INTERVAL 1 month);
SET #lastd = DATE_ADD(#nextm, INTERVAL 1 day);
SELECT
DATEDIFF(
IF(#lastd> free_until, free_until, #lastd),
IF(#today > free_from, #today, free_from)
)
FROM `test`
WHERE free_until >= #today AND free_from < #nextm
That should work. At least for your test data. But what day is 2013/02/30? :-)
Dont forget to change #today = CURDATE();
The best I can think of is something like:
WHERE free_until > CURDATE()
AND free_from < CURDATE() + INTERVAL '1' MONTH
That will get rid of any unnecessary rows. Then on the first row do in PHP:
date_diff(date(), free_until)
On the last row, do:
date_diff(free_from, strtotime(date("Y-m-d", strtotime($todayDate)) . "+1 month"))
Then on intermediate dates do:
date_diff(free_from, free_until)
Something to that effect, but this seems extremely clunky and convoluted...
From the top of my mind... first do a:
SELECT a.free_from AS a_from, a.free_until AS a_until, b.free_from AS b_from
FROM availability a
INNER JOIN availability b ON b.free_from > a.free_until
ORDER BY a_from, b_from
This probably will return a set of rows where for each row interval you have next i.e. greater intervals. The results are ordered strategically. You can then wrap the results in a partial group by:
SELECT * FROM (
SELECT a.free_from AS a_from, a.free_until AS a_until, b.free_from AS b_from
FROM availability a
INNER JOIN availability b ON b.free_from > a.free_until
ORDER BY a_from, b_from
) AS NextInterval
GROUP BY a_from, b_until
In the above query, add a DATE_DIFF clause (wrap it in SUM() if necessary):
DATE_DIFF(b_until, a_from)