Calculate average column value per day - mysql

I have the following table structure: Value (stores random integer values), Datetime` (stores purchased orders datetimes).
How would I get the average value from all Value rows across a full day?
I'm assuming the query would be something like the following
SELECT count(*) / 1
FROM mytable
WHERE DateTime = date(now(), -1 DAY)

You can GROUP BY the DATE part of DATETIME and use AVG aggregate function to find an average value for each group :
SELECT AVG(`Value`)
, DATE(`Datetime`)
FROM `mytable`
GROUP BY DATE(`Datetime`)

Looks like a simple AVG task:
SELECT `datetime`,AVG(`Value`) as AvgValue
FROM TableName
GROUP BY `datetime`
To find average of a specific day:
SELECT `datetime`,AVG(`Value`) as AvgValue
FROM TableName
WHERE `datetime`=#MyDate
GROUP BY `datetime`
Or Simply:
SELECT AVG(`Value`) as AvgValue
FROM TableName
WHERE `datetime`=#MyDate
Explanation:
AVG is an aggregate function used to find the average of a column. Read more here.

The following query will give you what u want..
SELECT DATE_FORMAT(thedate_field, '%Y-%m-%d') as theday, avg (value)
FROM mytable group by
DATE_FORMAT(thedate_field, '%Y-%m-%d')

Try It its work...
Select AVG(value),convert(nvarchar,DateTime,103) from table group by convert(nvarchar,DateTime,103)

Related

Avg function not returning proper value

I expect this query to give me the avg value from daily active users up to date and grouped by month (from Oct to December). But the result is 164K aprox when it should be 128K. Why avg is not working? Avg should be SUM of values / number of current month days up to today.
SELECT sq.month_year AS 'month_year', AVG(number)
FROM
(
SELECT CONCAT(MONTHNAME(date), "-", YEAR(DATE)) AS 'month_year', count(distinct id_user) AS number
FROM table1
WHERE date between '2020-10-01' and '2020-12-31 23:59:59'
GROUP BY EXTRACT(year_month FROM date)
) sq
GROUP BY 1
Ok guys thanks for your help. The problem was that on the subquery I was pulling the info by month and not by day. So I should pull the info by day there and group by month in the outer query. This finally worked:
SELECT sq.day_month, AVG(number)
FROM (SELECT date(date) AS day_month,
count(distinct id_user) AS number
FROM table_1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY 1
) sq
GROUP BY EXTRACT(year_month FROM day_month)
Do not use single quotes for column aliases!
SELECT sq.month_year, AVG(number)
FROM (SELECT CONCAT(MONTHNAME(date), '-', YEAR(DATE)) AS month_year,
count(distinct id_user) AS number
FROM table1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY month_year
) sq
GROUP BY 1;
Note the fixes to the query:
The GROUP BY uses the same columns as the SELECT. Your query should return an error (although it works in older versions of MySQL).
The date comparisons have been simplified.
No single quotes on column aliases.
Note that the outer query is not needed. I assume it is there just to illustrate the issue you are having.

Mysql. Change date format output on GROUP BY DAY query

I execute this query
SELECT * FROM graph WHERE ean IN ('00000000166330') group by DAY(created_at);
Getting those results:
# id, ean, avg_price, created_at
'58', '00000000166330', '2799.0000', '2020-06-11 16:43:27'
I want to change the date format returned of the created_at field.
I would like to get only the date, not the hour, and with the format: Day, month, Year.
My guess is that DATE_FORMAT should be used, but how to use it, grouping also by day?
Example here
You are not doing any aggregation, so remove group by
You can replace the operator IN with = because you are comparing against 1 value only
Use the function DATE() to get only the date part from created_at
You need a correlated subquery in the WHERE clause to get the row with the minimum id (since it does not matter whic row will be returned) of each day:
SELECT g.id, g.ean, g.avg_price, DATE_FORMAT(g.created_at, '%d-%m-%Y') created_at
FROM graph g
WHERE g.ean = '00000000166330'
AND g.id = (SELECT MIN(id) FROM graph WHERE ean = g.ean AND DATE(created_at) = DATE(g.created_at))
See the demo.
If you want distinct values without aggregation function you should use DISTINCT and for date you can use the date_format() function
SELECT DISTINCT DAY(created_at)
, date_format(date(created_at),'%d, %m, %Y') , id, avg_price
FROM graph WHERE ean = '00000000166330';
and when you have only a value you should use = and not IN operator.

Group data by Year and Month

I have a table with 4 columns:
1. customerID
2. dateAdded
3. productID
4. quantity
The format of dateAdded is like this: 20180730 (YearMonthDay).
I want to group the rows in the table by year and month.
I tried the code below but it doesn't work. I still see rows with the same year and month repeated, but different day.
SELECT dateAdded
, SUM(quantity)
FROM testTable
GROUP
BY DATE_FORMAT(dateAdded, '%Y%m')
, dateAdded
ORDER
BY dateAdded DESC
Any idea how to fix this?
Thank you
Do not group by what you do not want the data to be grouped. Since you provide dateAdded as a parameter to be grouped with, it splits the data by dateAdded and you gain nothing out of year-month grouping. Remove the columns from select/groupby that you use for grouping like this:
SELECT DATE_FORMAT(dateAdded, '%Y%m')
, SUM(quantity)
FROM testTable
GROUP BY
DATE_FORMAT(dateAdded, '%Y%m')
If you store dateAdded as 20180730, looks like it's a string, so it wont work with DATE_FORMAT function, you can use SUBSTRING instead
something like
SELECT dateAdded, SUM(quantity), SUBSTRING(dateAdded, 1, 6) as d
FROM testTable
GROUP BY d
ORDER BY dateAdded DESC
use year and month function
SELECT Year(dateAdded) as YearOfDate,Month(dateAdded) as MonthOfdate,
, SUM(quantity) as Qty
FROM testTable
GROUP
BY Year(dateAdded), Month(dateAdded)
ORDER BY dateAdded DESC

MySQL - How to select rows with the min(timestamp) per hour of a given date

I have a table of production readings and need to get a result set containing a row for the min(timestamp) for EACH hour.
The column layout is quite simple:
ID,TIMESTAMP,SOURCE_ID,SOURCE_VALUE
The data sample would look like:
123,'2013-03-01 06:05:24',PMPROD,12345678.99
124,'2013-03-01 06:15:17',PMPROD,88888888.99
125,'2013-03-01 06:25:24',PMPROD,33333333.33
126,'2013-03-01 06:38:14',PMPROD,44444444.44
127,'2013-03-01 07:12:04',PMPROD,55555555.55
128,'2013-03-01 10:38:14',PMPROD,44444444.44
129,'2013-03-01 10:56:14',PMPROD,22222222.22
130,'2013-03-01 15:28:02',PMPROD,66666666.66
Records are added to this table throughout the day and the source_value is already calculated, so no sum is needed.
I can't figure out how to get a row for the min(timestamp) for each hour of the current_date.
select *
from source_readings
use index(ID_And_Time)
where source_id = 'PMPROD'
and date(timestamp)=CURRENT_DATE
and timestamp =
( select min(timestamp)
from source_readings use index(ID_And_Time)
where source_id = 'PMPROD'
)
The above code, of course, gives me one record. I need one record for the min(hour(timestamp)) of the current_date.
My result set should contain the rows for IDs: 123,127,128,130. I've played with it for hours. Who can be my hero? :)
Try below:
SELECT * FROM source_readings
JOIN
(
SELECT ID, DATE_FORMAT(timestamp, '%Y-%m-%d %H') as current_hour,MIN(timestamp)
FROM source_readings
WHERE source_id = 'PMPROD'
GROUP BY current_hour
) As reading_min
ON source_readings.ID = reading_min.ID
SELECT a.*
FROM Table1 a
INNER JOIN
(
SELECT DATE(TIMESTAMP) date,
HOUR(TIMESTAMP) hour,
MIN(TIMESTAMP) min_date
FROM Table1
GROUP BY DATE(TIMESTAMP), HOUR(TIMESTAMP)
) b ON DATE(a.TIMESTAMP) = b.date AND
HOUR(a.TIMESTAMP) = b.hour AND
a.timestamp = b.min_date
SQLFiddle Demo
With window function:
WITH ranked (
SELECT *, ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp) rn
FROM source_readings -- original table
WHERE date(timestamp)=CURRENT_DATE AND source_id = 'PMPROD' -- your custom filter
)
SELECT * -- this will contain `rn` column. you can select only necessary columns
FROM ranked
WHERE rn=1
I haven't tested it, but the basic idea is:
1) ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp)
This will give each row a number, starting from 1 for each hour, increasing by timestamp. The result might look like:
|rest of columns |rn
123,'2013-03-01 06:05:24',PMPROD,12345678.99,1
124,'2013-03-01 06:15:17',PMPROD,88888888.99,2
125,'2013-03-01 06:25:24',PMPROD,33333333.33,3
126,'2013-03-01 06:38:14',PMPROD,44444444.44,4
127,'2013-03-01 07:12:04',PMPROD,55555555.55,1
128,'2013-03-01 10:38:14',PMPROD,44444444.44,1
129,'2013-03-01 10:56:14',PMPROD,22222222.22,2
130,'2013-03-01 15:28:02',PMPROD,66666666.66,1
2) Then on the main query we select only rows with rn=1, in other words, rows that has lowest timestamp in each hourly partition (1st row after sorted by timestamp in each hour).

How to count rows in db for each hour?

In table are two columns: Datestamp like 2012-12-16 with type date and Timestamp like 12:22:59 with type time. Is it possible to get count of rows for each hour for specific day with 1 sql? On return i need to get 24 numbers.
Something like this:
SELECT COUNT(*) FROM your_table
WHERE `Datestamp` = '2012-12-16'
GROUP BY HOUR(`Timestamp`)
SELECT datestamp as day, hour(timestamp) as hour, count(*)
FROM your_table
GROUP BY datestamp, hour(timestamp)