Split months into 4 and retrieve the average value per day - php

This is the output of a query on a temporary table created in a complex stored procedure in MySQL :
The goal now is to have the average duration per day like we have here, but for each week by month
So I want to take every month and divide it into 4 set of days with the average duration per day.
Therefore no matter how many days there are in the month, I will have 4 values for it.
How can I do that ?
Note : If it is easier I can do it with php, since I will use the data with this language.

You have a query that groups per day, e.g.:
select
the_date as day,
sec_to_time(avg(timestampdiff(second, start_time, end_time))) as duration
from ...
group by the_date;
You want days 1-7, 8-14, 15-21, 22-end per month instead. Use CASE WHEN to build the groups.
select
year(the_date) as year,
month(the_date) as month,
case
when day(the_date) <= 7 then '01-07'
when day(the_date) <= 14 then '08-14'
when day(the_date) <= 21 then '15-21'
else '22-end'
end as day_range,
sec_to_time(avg(timestampdiff(second, start_time, end_time))) as duration
from ...
group by year, month, day_range
order by year, month, day_range;

Related

How to write mysql query to sort data by month starting from current month

I have one table with one column named 'created_at'. Now i want to all records group by month and order by month start from current month.
Here is the MySQL query I've written so far:
SELECT count(id),MONTH(created_at) as month
FROM `perks`
GROUP BY created_at
ORDER BY MONTH(created_at)
and out put is:
I need month august(8) first as it is current month then 9,10,11,12,1,2... so on.
Can any buddy help to resolve this issue?
As jaymin indicated you need to group by the month, not the time
GROUP BY MONTH(created_at)
Also if there are times before now that need excluding, use a where clause:
WHERE created_at > current_date()
If your data includes dates next year, you'll probably need to group by year(created_at), month(created_at) and order by this too, unless you don't care that next years august is rolled into this years august etc
If the intention is to roll everything together, and have the months go round in a full circle starting with the current month, you'll need to:
ORDER BY CASE WHEN MONTH(created_at) >= MONTH(current_date()) THEN 1 ELSE 2, MONTH(created_at)
You can use
GROUP BY MONTH(CURRENT_DATE())

Ranking query from the last x months

I want to get all records from the last x months from my MySQL server. Using 2 months for example(Not from last 2 months, like last 60 days, but from the entire past month and so on. If actual month is april, I want all records from february and march).
I've tried some queries and the last one is
SELECT id FROM ranking WHERE (end_date BETWEEN DATE_FORMAT(NOW(), '%Y-%m-01') AND DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 2 MONTH), '%Y-%m-%d'))
"end_date" is my date column which is a DATE column "2017-04-07".
That query above just returns nothing and I cant figure out where is the error.
Try this:
SELECT id
FROM ranking
WHERE end_date BETWEEN
DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 3 MONTH)) INTERVAL 1 DAY)
AND LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH));
It calculates dates as like this:
For start date in range, it subtracts 3 months from current date, gets the last day of that month and adds a day in it to get the first day of next month (1st February in our case)
For end date, it subtracts one month from current date and gets the last day of that month (31st March in our case)
Try without convert it to string, And BETWEEN requires min date first.
SELECT id
FROM ranking
WHERE end_date BETWEEN LAST_DAY(CAST(NOW() as date) - INTERVAL 2 MONTH
AND CAST(NOW() as date)

Get the number of added values in Database in the last month by weeks?PHP Mysqli

I want to show the number of rows added in database per week in last 1 month:
i already tried this query but it shows the number by weeks for all the time i mean not just the last 1 month. so that code shows the number within the last 1 week
$result = $db->query("SELECT count(*)
FROM reclamations
WHERE work = 'done'
AND reclamation_date >= NOW() - INTERVAL 1 week")
But actually i want to get the number by week yeah but just for the last 1month
If you want to get the count per week for the last month, you will need to change your interval to MONTH and add a GROUP BY to your existing query. You can use the WEEK() MySQL function to get the week of the year value from your date. Note that if there is any missing data in your time series - a week with no data - it will be missing from the results.
SELECT WEEK(reclamation_date) week_of_year, count(*) entry_count,
FROM reclamations
WHERE work = 'done'
AND reclamation_date >= NOW() - INTERVAL 1 MONTH
GROUP BY WEEK(reclamation_date)

Mysql intersection of datetimes

I have the table Vacation in mysql DB. The table has datetime_from and datetime_to. To have a vacation from Monday to Friday means there is only one record in the table with two timestamps
date_from = 'MONDAY_DATE 00:00:00'
date_to = 'FRIDAY_DATE 23:59:59'
The working time is from 8:00 to 16:00 every day. I would like to get all the working time that employee missed during his vacation (in hours for example). It's 8hrs a day x 5.
Im able to do that in 5 queries (one for every day and then sum up with PHP) as an intersection of date intervals BUT is it possible to perform it in only one mysql query?
SELECT SUM(date_to - date_from) as seconds_missed FROM Vacation
WHERE ...
That would give you the total number of seconds missed for an employee assuming the where clause matches it against a given user. I guess you could also add conditions in your where clause to only grab dates in a certain range (i.e. worked missed that week).

MySQL AVG(COUNT(*) - Orders By day of week query?

This query has baffled me... I've searched the web work over a day now and I have tried numerous things.
I want to get the avg number of orders for every day of the week from my db. I can pull the total # with COUNT just fine. But I just can't figure out how to get the AVG of COUNT on a GROUP BY. I've tried subqueries... functions... everything... nothing works... maybe someone can throw me a bone.
Here is the query I started with below. I know AVG(COUNT(*)) won't work but I'll leave it at that because it shows what I want to do.
SELECT
AVG(COUNT(*)) AS avgorders,
SUM(total) AS ordertotal,
DAYNAME(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) AS day
FROM data
GROUP BY day
ORDER BY DAYOFWEEK(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) ASC
To get the average you don't need the grand totals for each day, you need multiple daily totals for each day.
Day | Count
__________________
Monday 5
Tuesday 4
Monday 6
Tuesday 3
... ...
Then you can average those numbers. I.e (5+6)/2 for Monday.
Something like this should work:
SELECT day_of_week, AVG(order_count) average_order FROM
(
SELECT DAYNAME(order_date) day_of_week,
DAYOFWEEK(order_date) day_num,
TO_DAYS(order_date) date,
count(*) order_count
FROM data
GROUP BY date
) temp
GROUP BY day_of_week
ORDER BY day_num
UPDATE: I was originally wrong. Group the inner SELECT by the actual date to get the correct daily totals. For instance, you need to get how many orders happened Monday (2/1/10) and Monday (2/8/10) separately. Then average those totals by the day of the week.
This will do, assuming that order_time is date or datetime field ( everyone would be hapier this way ;) ). Of course there is some approximation, because oldest order can be in Friday and newest in Monday, so amount of every day of week isn't equal, but creating separate variable for every day of week will be pain in the ass. Anyway I hope it will be helpful for now.
SET #total_weeks = (
SELECT
TIMESTAMPDIFF(
WEEK,
MIN(order_time),
MAX(order_time)
)
FROM data
);
SELECT
DAYNAME(order_time) AS day_of_week,
( COUNT(*) / #total_weeks ) AS avgorders,
COUNT(*) AS total_orders
FROM
data
GROUP BY
DAYOFWEEK(order_time)
I know this is old, but i was searching for a similar solution hoping to find something someone else had used. In hopes of not doing a sub query, i came up with the below and would love any feed back!
SELECT dayofweek(`timestamp`) as 'Day',count(`OrderID`)/count(DISTINCT day(`timestamp`)) as 'Average' FROM `Data` GROUP BY dayofweek(`timestamp`)
The idea is to divide the total orders on a given day of the week, by the total number of "Mondays" or whatever day it is. What this does not account for would be any days that had zero orders would not lower the average. That may or may not be desired depending on the application.
What you are asking doesn't make sense to me... AVG is an aggregate function and so is COUNT. What's wrong with the query above but just use: COUNT(*) AS avgorders?
Lets say you had 3 rows for day1, 2 rows for day2, 5 rows for day3, and 9 rows for day4... do you want to get back a single row result that tells you:
avgorders = (3 + 2 + 2 + 5 + 9) / 5 = 21 / 5 = 4.2
ordertotal = (3 + 2 + 2 + 5 + 9) = 21
I don't think you can get that in a single query, and you'd be better off doing the second round of aggregation in a server side language like PHP operating on the results of the first aggregation.

Categories