How can I make an average of dates in MySQL?
This seems a bit hackish, but will work for dates beteen ~ 1970 and 2030 (on 32 bit arch). You are essentially converting the datetime values to integer, averaging them, and converting the average back to a datetime value.
SELECT
from_unixtime(
avg(
unix_timestamp(date_one)-unix_timestamp(date_two)
)
)
FROM
some_table
WHERE
some-restriction-applies
There is likely a better solution out there, but this will get you by in a pinch.
How do I calculate an average date in SQL?
Try:
SELECT FROM_UNIXTIME(AVG(UNIX_TIMESTAMP(created))) FROM table
Calculating average time between dates in SQL
You can use window functions. I am thinking row_number()
to enumerate the projects of each user ordered by creation date, and lag()
to get the date when the previous project was created:
select rn, avg(datediff(created_at, lag_created_at)) avg_diff_days
from (
select t.*,
row_number() over(partition by user_id order by created_at) rn,
lag(created_at, 1, created_at) over(partition by user_id order by created_at) lag_created_at
from mytable t
) t
group by rn
This gives you the average difference in days, which is somehow more accurates that months. If you really want months, then use timestampdiff(month, lag_created_at, created_at)
instead of datediff()
- but be aware that the function returns an integer value, hence there is a loss of precision.
How to get AVG from DATE (not datetime, timestamp) and return DATE (not datetime, timestamp)
Convert the date to unixtime, take the average and convert back to datetime:
select cast(from_unixtime(avg(unix_timestamp(dt))) as date)
from data;
Unixtime is simply seconds elapsed from 1970-01-01, so it is an integer where you can calculate the average from.
MySql average date difference
The average is just the largest value minus the smallest divided by one less than the number of values. So:
select datediff(max(date), min(date)) / nullif(count(*) - 1, 0)
from t;
You can easily see this if you look at the numbers:
1
5 . . . 4
10 . . . 5
19 . . . 9
The average difference is (4 + 5 + 9) / 3 = 6.
It is not a coincidence that (19 - 1) / 3 = 6 as well. It is a mathematical certainty.
You can easily see this. The average difference is:
( (5 - 1) + (10 - 5) + (19 - 10) ) / 3
You can rearrange this:
( -1 + (5 - 5) + (10 - 10) + 19 ) / 3
which is:
( 19 - 1 ) / 3
Calculate average, minimum, maximum interval between date
If your mysql version didn't support lag
or lead
function.
You can try to make a column use a subquery to get next DateTime. then use DATEDIFF
to get the date gap in a subquery.
Query 1:
SELECT avg(diffDt),min(diffDt),MAX(diffDt)
FROM (
SELECT DATEDIFF((SELECT transaction_date
FROM T tt
WHERE tt.transaction_date > t1.transaction_date
ORDER BY tt.transaction_date
LIMIT 1
),transaction_date) diffDt
FROM T t1
) t1
Results:
| avg(diffDt) | min(diffDt) | MAX(diffDt) |
|-------------|-------------|-------------|
| 2 | 1 | 3 |
if your mysql version higher than 8.0 you can try to use LEAD
window function instead of subquery.
Query #1
SELECT avg(diffDt),min(diffDt),MAX(diffDt)
FROM (
SELECT DATEDIFF(LEAD(transaction_date) OVER(ORDER BY transaction_date),transaction_date) diffDt
FROM T t1
) t1;
| avg(diffDt) | min(diffDt) | MAX(diffDt) |
| ----------- | ----------- | ----------- |
| 2 | 1 | 3 |
View on DB Fiddle
Make the average of values for time intervals mysql
One way could be to extract date
and hour
part from the timestamp
and group by the resultant.
select DATE_ADD(date(fecha), INTERVAL EXTRACT(HOUR FROM fecha) HOUR) as FECHA_DATE_HOUR,
avg(Valor_Dispositivo) as Valor_Dispositivo
from Telegramas
group by date(fecha), EXTRACT(HOUR FROM fecha);
Result:
+---------------------+-------------------+
| FECHA_DATE_HOUR | Valor_Dispositivo |
+---------------------+-------------------+
| 14.12.2017 11:00:00 | 4.3333 |
| 14.12.2017 12:00:00 | 5.0000 |
+---------------------+-------------------+
DEMO
How to average a value in a time window for multiple days, in Mysql?
You do not need to use Subquery, to get the data and then calculate the average in the Outer query. It can be done without the subquery itself.
In order to get the average value for different dates, you can remove the WHERE
condition on date, to get the data for all the date(s). You can also change the WHERE
condition on date to include a range instead.
You also seem to want results for different id
values. We can get rid of WHERE
condition on id
as well.
Eventually, you can do a GROUP BY
on the id
and date
, to get individual rows idwise, and then datewise.
SELECT
id,
DATE(dt)
AVG(val)
FROM test
WHERE
TIME(dt) BETWEEN '00:00' AND '02:00'
GROUP BY id, DATE(dt)
find average interval dates from the date colum in mysql server
nb: It is easier to add another answer than to edit the former.
You need to use JOINED "derived tables" instead of "correlated subqueries". You will find this far more efficient too. Here you need to average some values so the derived table involves a group by.
To use the technique where a previous value is carried over to the next row, you must cross join some variables, don't comment this out.
The order by clause is vital to this technique. Here you must use a combined order involving dam_id as well as birth_date otherwise you would get a rubbish result.
Hopefully these queries will identify the logic for you. The first helps display the detailed logic of each row. The second displays the "derived table" before it is joined, and the third displays the effect of joining the derived table to the source (detail) table.
Query 1:
SELECT
IF((t2.dam_id=@prev_dam), datediff(t2.birth_date,@prev_value), NULL) difference
, @prev_dam
, @prev_value
, t2.dam_id
, t2.birth_date
, @prev_dam := t2.dam_id
, @prev_value := t2.birth_date
FROM cattle_info_tbl t2
CROSS JOIN (SELECT @prev_dam:=null x, @prev_value:=str_to_date(NULL,'%Y-%M-%d') y) y
order by t2.dam_id, t2.birth_date
Results:
| difference | @prev_dam | @prev_value | dam_id | birth_date | @prev_dam := t2.dam_id | @prev_value := t2.birth_date |
|------------|-----------|-------------|--------|------------|------------------------|------------------------------|
| (null) | (null) | (null) | S6040 | 2008-04-30 | S6040 | 2008-04-30 |
| 351 | S6040 | 2008-04-30 | S6040 | 2009-04-16 | S6040 | 2009-04-16 |
| 336 | S6040 | 2009-04-16 | S6040 | 2010-03-18 | S6040 | 2010-03-18 |
| (null) | S6040 | 2010-03-18 | S6093 | 2008-04-04 | S6093 | 2008-04-04 |
| 376 | S6093 | 2008-04-04 | S6093 | 2009-04-15 | S6093 | 2009-04-15 |
| 353 | S6093 | 2009-04-15 | S6093 | 2010-04-03 | S6093 | 2010-04-03 |
| 344 | S6093 | 2010-04-03 | S6093 | 2011-03-13 | S6093 | 2011-03-13 |
| 444 | S6093 | 2011-03-13 | S6093 | 2012-05-30 | S6093 | 2012-05-30 |
| 351 | S6093 | 2012-05-30 | S6093 | 2013-05-16 | S6093 | 2013-05-16 |
| 362 | S6093 | 2013-05-16 | S6093 | 2014-05-13 | S6093 | 2014-05-13 |
| (null) | S6093 | 2014-05-13 | S6094 | 2008-03-29 | S6094 | 2008-03-29 |
| 371 | S6094 | 2008-03-29 | S6094 | 2009-04-04 | S6094 | 2009-04-04 |
| 409 | S6094 | 2009-04-04 | S6094 | 2010-05-18 | S6094 | 2010-05-18 |
| 300 | S6094 | 2010-05-18 | S6094 | 2011-03-14 | S6094 | 2011-03-14 |
| 1185 | S6094 | 2011-03-14 | S6094 | 2014-06-11 | S6094 | 2014-06-11 |
Query 2:
SELECT dam_id, AVG(difference) age
FROM (
SELECT
IF((t2.dam_id=@prev_dam), datediff(t2.birth_date,@prev_value), NULL) difference
, t2.dam_id
, @prev_dam := t2.dam_id
, @prev_value := t2.birth_date
FROM cattle_info_tbl t2
CROSS JOIN (SELECT @prev_dam:=null x, @prev_value:=str_to_date(NULL,'%Y-%M-%d') y) y
ORDER BY t2.dam_id, t2.birth_date
) b
GROUP BY dam_id
Results:
| dam_id | age |
|--------|----------|
| S6040 | 343.5 |
| S6093 | 371.6667 |
| S6094 | 566.25 |
Query 3:
SELECT
t1.dam_id as cow_id
, av.age
FROM cattle_info_tbl t1
LEFT JOIN (
SELECT dam_id, AVG(difference) age
FROM (
SELECT
IF((t2.dam_id=@prev_dam), datediff(t2.birth_date,@prev_value), NULL) difference
, t2.dam_id
, @prev_dam := t2.dam_id
, @prev_value := t2.birth_date
FROM cattle_info_tbl t2
CROSS JOIN (SELECT @prev_dam:=null x, @prev_value:=str_to_date(NULL,'%Y-%M-%d') y) y
ORDER BY t2.dam_id, t2.birth_date
) b
GROUP BY dam_id
) av ON t1.dam_id = av.dam_id
WHERE t1.herd_id = 'H38' AND t1.dam_id<>''
Results:
| cow_id | age |
|--------|----------|
| S6093 | 371.6667 |
| S6093 | 371.6667 |
| S6094 | 566.25 |
| S6094 | 566.25 |
| S6093 | 371.6667 |
| S6040 | 343.5 |
| S6094 | 566.25 |
| S6093 | 371.6667 |
| S6040 | 343.5 |
| S6040 | 343.5 |
| S6093 | 371.6667 |
| S6094 | 566.25 |
| S6093 | 371.6667 |
| S6094 | 566.25 |
| S6093 | 371.6667 |
NOTE: I think you complicate everything by confusing dam_id with cow_id. This does not appear to be correct. My guess is that animal_id is more likely to be the correct column to relabel as cow_id.
Getting total average between dates
You can find average of total for each user within 10 days date range from intial sales date like this:
select avg(sale_cost)
from (
select sum(t.sale_cost) sale_cost
from your_table t
join (
select user_id, min(sale_date) start_date, date_add(min(sale_date), interval 10 day) end_date
from your_table
group by user_id
) t2 on t.user_id = t2.user_id
and t.sale_date between t2.start_date and t2.end_date
group by t.user_id
) t;
It finds the first sale_date and date 10 days after this for each user. Then joins it with the table to get total for each user within that range and then finally average of the above calculated totals.
Demo
If you want to find the average between overall first sale_date (not individual) and 10 days from it, use:
select avg(sale_cost)
from (
select sum(t.sale_cost) sale_cost
from your_table t
join (
select min(sale_date) start_date, date_add(min(sale_date), interval 10 day) end_date
from your_table
) t2 on t.sale_date between t2.start_date and t2.end_date
group by t.user_id
) t;
Demo
Related Topics
Update Query Using Subquery in SQL Server
Should Every SQL Server Foreign Key Have a Matching Index
Finding Node Order in Xml Document in SQL Server
Counting the Number of Occurrences of a Substring Within a String in Postgresql
How to Search SQL Column Containing JSON Array
How to Transform Comma Separated Column into Multiples Rows in Db2
Selecting Column Names That Have Specified Value
How to Represent a Data Tree in SQL
Psql Invalid Command \N While Restore SQL
Oracle 'Partition By' and 'Row_Number' Keyword
Timestamp Difference in Hours for Postgresql
How to Implement SQL Intersect and Minus Operations in Ms Access
Does Assigning Stored Procedure Input Parameters to Local Variables Help Optimize the Query