MySQL Aggregate function in other aggregate function - mysql

I'm having a table with posts. Like (id int, date datetime).
How can I select average posts per day count for each month with one sql request?
Thank you!

This should do it for you:
select month, avg(posts_per_day)
from (select day(date), month(date) as month, count(*) as posts_per_day
from posts group by 1,2) x
group by 1
Explanation: Because you are doing an aggregate on an aggregate, there is no getting around doing a query on a query:
The inner query calculates the number per day and captures the month.
The outer query averages this count , grouping by month.

You can get the number of posts per month like this:
SELECT COUNT(*) AS num_posts_per_month FROM table GROUP BY MONTH(date);
Now we need the number of days in a month:
SELECT COUNT(*) / DATEDIFF(MAKEDATE(YEAR(date), MONTH(date)) + INTERVAL 1 MONTH, MAKEDATE(YEAR(date), MONTH(date))) AS avg_over_month
FROM table GROUP BY MONTH(date);
This will get the average number of posts per day during the calendar month of the post. That is, averages during the current month will continue to rise until the end of the month. If you want real averages during the current month, you have to put in a conditional to get the true number of elapsed days.

Related

Query for # of new user per week - how to order by year/week?

I'm working to write a MySQL query that outputs the number of new users created by week.
My user table is:
id | created_at
My query:
SELECT YEAR(created_at) AS Year, DATE_FORMAT(created_at, '%b %e') AS Week, COUNT(*) AS total
FROM users
GROUP BY Year, Week;
The problem:
Years: I would like the most recent year to be at the top, currently the oldest year is at the top of the output.
Weeks: The week column is not sorted based on the calendar. For example, the last records shows: 2019 | May 9 | 100
Where I'd like the year and week sorted.
I think you'll find the function YEARWEEK() helpful, not only for the grouping, but also for the ordering.
Also, your use of DATE_FORMAT() doesn't look right, because you're outputing the %e, which is the day of the month, yet you're grouping by week?
SELECT DATE_FORMAT(created_at, '%Y %b %v') AS date, COUNT(*) AS total
FROM users
GROUP BY YEARWEEK(created_at)
ORDER BY YEARWEEK(created_at) DESC;

How to get total count value each day upto 5 days

"SELECT count(id) AS total FROM participant where dateofbooking='$datepick'";
I am using this code. But its showing only one date(selected date from php) count. but I want to select single date and it should show me upto 5 days daily wise count booking.
output should be like this:-
2018-05-20------>48
2018-05-21------>58
2018-05-22------>67
2018-05-23------>78
2018-05-24------>43
You can use DATE_ADD() :
SELECT dateofbooking, count(id) AS total
FROM participant
WHERE dateofbooking >= $datepick AND
dateofbooking <= DATE_ADD($datepick, INTERVAL 5 DAY)
GROUP BY dateofbooking;
You can group it by the date column you are using, and if you want multiple days you can add dateofbooking >= some_start_date and dateofbooking <= some_end_date
"SELECT count(id) AS total FROM participant where dateofbooking='$datepick' group by dateofbooking";
the multiple may look something like
"SELECT count(id) AS total FROM participant where dateofbooking>='$datepickstart' AND dateofbooking<='$datepickend' group by dateofbooking";

related to query using SQL

In oracle sql, how to get the count of newly added customers only for the month of april and may and make sure they werent there in the previous months
SELECT CUSTOMER ID , COUNT(*)
FROM TABLE
WHERE DATE BETWEEN '1-APR-2018' AND '31-MAY-2018' AND ...
If we give max (date) and min(date), we can compare the greater date to check if this customer is new , correct?
expected output is month count
april ---
may ---
should show the exact count how many new customers joined in these two months
One approach is to use aggregation:
select customer_id, min(date) as min_date
from t
group by customer_id
having min(date) >= date '2018-04-01 and
min(date) < date '2018-06-01';
This gets the list of customers (which your query seems to be doing). To get the count, just use count(*) and make this a subquery.

Moving average in SQL

I have a MySQL database populated with power consumption over 20 years.
I want to query the average of the power consumption over every month, from a given month.
For example with this database,
date power_consumption
2014/03/30 30
2014/04/30 40
2014/05/30 50
2014/06/30 20
The result would be, from 2014/04
month average_so_far_from_april_2014
2014/04 40.0
2014/05 45.0
2014/06 36.667
If I cannot achieve this in one query, what query should I go for to retrieve the most useful data for this task? (My naive approach is to query the whole table out and calculate the average in my application.)
Join the table of sub query against the consumption table which gets the unique months against the table of consumption, with a join condition that the year / month is less than or equal to the one from the sub query and use the AVG aggregate function on the power consumption from the table grouped by the year / month
Something like this:-
SELECT consumption_month,
AVG(b.power_consumption)
FROM
(
SELECT DISTINCT DATE_FORMAT(`date`, '%Y%m') AS consumption_month FROM consumption_table a
) a
INNER JOIN consumption_table b
ON consumption_month >= DATE_FORMAT(b.`date`, '%Y%m')
WHERE b.`date` >= '2014/04/01'
GROUP BY consumption_month
SQL fiddle:-
http://www.sqlfiddle.com/#!2/16588/2
If you only had one record per month you could simplify it more by just doing a join of the table against itself without the need for the sub query.
GROUP BY is for this kind of problems. The average is calculated for each distinct value of the expression the the GROUP BY clause.
SELECT DATE_FORMAT(date, '%Y/%m'), AVG(power_consumption)
FROM table_name
WHERE date > ...
GROUP BY DATE_FORMAT(date, '%y/%m')
ORDER BY DATE_FORMAT(date, '%y/%m')
You get the average for each month, DATE_FORMAT(date, '%y/%m') is year and month in format YYYY/MM

total count each day sorted, result grouped by week

My query looks like this right now pretty straightforward:
select
count(*),
date(visit_date),
DATE_FORMAT(visit_date,"%a")
from visits
group by date(visit_date)
Here is the result:
http://d.pr/FmMg
what I want to happen is:
for each week the count is sorted
Can you modify my query so it satisfies the criteria?
Assuming, you no longer need the count by day and are ONLY looking for count by week:
SELECT
count(*),
yearweek(visit_date)
FROM visits
GROUP BY yearweek(visit_date)
ORDER BY yearweek(visit_date) ASC;
Are you trying to do like this?
- you can use Datepart to get week number and sort by that.
select
count(*),
date(visit_date),
DATE_FORMAT(visit_date,"%a")
from
visits
group by
date(visit_date)
order by
datepart(yyyy,visit_date),
datepart(wk,visit_date),
count(*)