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

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.

Related

How to get week numbers for given two dates in different year - php / mysql?

Actually I need to get the week numbers with total quantity. please check the below query.
SELECT WEEK(oi.lastupdated) AS week_number, SUM(oi.quantity) as 'total' FROM orders_item oi
JOIN orders ord on ord.orderid=oi.orders_orderid
JOIN product prod on prod.sku=oi.sku
WHERE oi.sku= 'ZFAFBK'
AND ord.status = 4
AND oi.lastupdated >= DATE_SUB(NOW(),INTERVAL 1 YEAR)
GROUP BY week_number
ORDER BY week_number DESC
The above query will return the number of weeks for the year. but its resetting the week number for the different year.
Example if i want to find week number 2017-02-19 to 2018-02-19, then the week numbers start from 1 for the 2018. But I want 0 - 52 weeks even though different years.
How can i solve this issue?
Thanks.

Select Sum of hours for specific month and year for specific user

Hello I am trying to realize a query where from DB with hours and dates I can select sum of all hours for certain department, in certain year.
Table example is the following:
So far the query which I am generating is the following:
SELECT t.clientid, t.date, t.department, t.time,
(SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `time` ) ) ) FROM time_management WHERE YEAR(t.date)='$year' AND MONTH(t.date)= 12 GROUP BY t.clientid ) as january,
(SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `time` ) ) ) FROM time_management WHERE YEAR(t.date)='$year' AND MONTH(t.date)= 2 GROUP BY t.clientid ) as february
FROM time_management t GROUP by t.clientid
What I would like this to do is select sum of all hours for the month of January 2016. in the current state I am getting the result of sum of all hours for all clients and I would like to get result for client by client:
Current Result is:
So what I am searching for is how to get the sum of the times result grouped by clientid and get 2 results not only one. The sum for both client id. independently summed for each one of them ?
Any help will be very appreciate. Thank you!
You should be able to do that without the subquery -
SELECT `date`, `department`, SUM(`time`)
FROM `time_management`
WHERE YEAR(`date`)='$year' AND MONTH(`date`)= 12
GROUP BY `client_id`
I recommend you store you time in the database in seconds - the only time it needs to show as hours and minutes is when it's formatted to show on the client's screen. If you do store it as strings, you will have to put all that converting stuff back in.
Looking at it more, I'd also recommend storing your year and month either as separate columns, or as integers based on a pattern: 201612, perhaps, or something like that. That will clean up your where clause as well.

Mysql find dates using where in clause, or dates nearest to those in array

I have the following code and query:
//$month is an array of datetime objects
foreach($month as $key => $indMonth){
$formattedMonth[] = $month[$key]->format('Y-m-d');
}
$formattedMonths = implode("','",$formattedMonth);
$query = "SELECT id,date FROM table WHERE date in ('$formattedMonths') ORDER by date DESC";
The database holds dates for the past 450 days, but it is imperfect and there are some missing days. The point of the script is to retrieve data from the current day of the month and then the corresponding day on the five previous months, but I need a failsafe for when a date happens to be missing.
How can I modify this query so it picks either the date in the "where in" portion of the query or it finds the date nearest to that particular date in the array?
Is this best to do in the query, or am I better off returning a more complete data set, then using PHP to find out if the date I want is available?
MySQL offers some decent date arithmetic. For example, if you have the date '2015-11-10' (10-Nov-2015) you can get the same day three months prior with this expression:
'2015-11-10` - INTERVAL 3 MONTH
That will kick back '2015-08-10', which is what you want.
This date arithmetic works predictably even with longer and shorter months, and with leap years. For example,
'2015-03-31' - INTERVAL 1 MONTH, '2016-03-31' - INTERVAL 1 MONTH
gives back '2015-02-28', '2016-02-29' as you might expect. And
'2015-03-31' - INTERVAL 2 MONTH, '2016-03-31' - INTERVAL 2 MONTH
gives back '2015-03-31', '2016-03-31'. Perfect.
Now, only you can decide whether this predictable behavior is correct for your application: only you know what you want to do with the previous five months of data, when the day in question is near the end of the month.
Let's assume it's correct and move on. Here is a subquery that can be used to generate a sequence of six dates, one day per month ending today.
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
We can use this little query as a subquery, and LEFT JOIN it to your data. That would work like this:
SELECT id, day_of_month
FROM (
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
) days
LEFT JOIN table ON table.date = days.day_of_month
This is a cool way to do it because you'll always get at least one row in the resultset for each date in the list, even if there's nothing matching in table.
The closest date gets a little hairier. It's possible to write a query like that. But MySQL lacks a WITH clause so the query is ridiculously repetitive.

select rows if the sum of a field in the table is less than X for each date in the table

this is my first question so forgive me if I am doing this wrong. I have been trying to think up a query for the above described problem and I can't seem to get anywhere.
SELECT SUM(slots) AS totals,date
FROM
(
SELECT start, end, date, slots
FROM 1000_appointments
WHERE date > NOW() AND HOUR(end) <= 12 AND employeeID='1000001'
) q
GROUP BY date HAVING totals < 6
This gets me the days where the total of slots is less than 6 and that is great but I also need all rows for that date and, if at all possible, dates that have no entries in the table. I could possible do the sorting and listing in php but I figured there might be a more elegant way of doing this within mysql.
I hope this describes the problem well enough. The reasoning behind this is that I need to find dates where "slots" are still available ie dates that aren't booked out.
Thank you, for your help in advance.
Wrapping that will get all the rows for you:
SELECT start, end, a.date, slots, totals
FROM 1000_appointments a
JOIN
(SELECT SUM(slots) AS totals,date
FROM 1000_appointments
WHERE date > NOW() AND HOUR(end) <= 12 AND employeeID='1000001'
GROUP BY date HAVING totals < 6
) t
where a.date = t.date
It's not so easy to get the dates not in the table. It will probably require using cursors. I'd recommend doing this in your php code.

how to count the number of dates in a table

I have a small custom blog type site and I keep track of my posts with a datetime field in the DB that hold a current_timestamp when entered.
I am working on a pagination setup and want to figure out how many unique days there are in my DB.
For example in the below screen shot there are 19 entries but only entered on 5 different days.
I want to be able to find the number of unique days in the DB. In the above shot 5.
This way I can paginate my posts by groups of days, say 7 but still show all the posts for all those days regardless of if one day has more posts or one day has none.
EX for page 1 showing the first 7 days of posts:
Jan 1st
+post
+post
+post
Jan 3
+post
Jan 4
+post
+post
Jan 5
+post
Jan 6
+post
+post
Jan 7
+post
Jan 8
+post
+post
How is the best way to get this data or paginate in this way?
Thanks
Try below:
select count(*),date from tablename group by left(date,10)
above query will give count of unique days.
This will give you the amount of posts per day:
select from_days(to_days(date)) day, count(*) from t
group by day
You can then apply a limit to the amount of records (days) to paginate them per 7 days:
select from_days(to_days(date)) day, count(*) from t
group by day
limit 7
Now, if you want to get the actual posts (I think that is what you want), you can do this:
select date, file from t t1 join (
select to_days(date) day from t
group by day
order by day desc
limit 7
) t2
on to_days(t1.date) = t2.day
This will give you all posts for the 7 most current days. Is that what you where looking for?
Edit:
I may be misinterpreting or did not ask my question well but I want the the count of all total unique days not posts. - ian
LOL: That's easier :)
select count(distinct to_days(date)) from t
I guess what you are looking for is
SELECT count(*) from table group by DATE(date)
the trick is to map datetime into date via DATE() function
UPDATE: sorry I missinterpreted your question. This will return the number of posts in each day.
To get number list of unique days you could do
SELECT DISTINCT DATE(datetime) from table
To get number of unique days you could either check the count of it in your back-end language or make a subquery, like:
select count(*) from (select distinct date(datetime) from table) as res

Categories