I need to calculate 10 minute average of my MySql table. But the default average it's not what I want. I've a code for "default" average:
SELECT Date, convert((min(Time) DIV 1000)*1000,time) as Time, ROUND(AVG(Value),2) FROM RawData
GROUP BY Date, Time DIV 1000
How can I calculate average like this:
http://prntscr.com/8k4slp
And one more thing... I need to prevent the average calculation of incomplete intervals. How can I do this?
Related
I have a table that looks like this:
id
slot
total
1
2022-12-01T12:00
100
2
2022-12-01T12:30
150
3
2022-12-01T13:00
200
There's an index on slot already. The table has ~100mil rows (and a bunch more columns not shown here)
I want to sum the total up to the current moment in time (EDIT: WASN'T CLEAR INITIALLY, I WILL PROVIDE A LOWER SLOT BOUND, SO THE SUM WILL BE OVER SOME NUMBER OF DAYS/WEEKS, NOT OVER FULL TABLE). Let's say the time is currently 2022-12-01T12:45. If I run select * from my_table where slot < CURRENT_TIMESTAMP(),
then I get back records 1 and 2.
However, in my data, the records represent forecasted sales within a time slot. I want to find the forecasts as of 2022-12-01T12:45, and so I want to find the proportion of the half hour slot of record 2 that has elapsed, and return that proportion of the total.
As of 2022-12-01T12:45 (assuming minute granularity), 50% of row 2 has elapsed, so I would expect the total to return as 150 / 2 = 75.
My current query works, but is slow. What are some ways I can optimise this, or other approaches I can take?
Also, how can we extend this solution to be generalised to any interval frequency? Maybe tomorrow we change our forecasting model and the data comes in sporadically. The hardcoded 30 would not work in that case.
select sum(fraction * total) as t from
select total,
LEAST(
timestampdiff(
minute,
datetime,
current_timestamp()
),
30
) / 30 as fraction
from my_table
where slot <= current_timestamp()
Consider computing your sum first, then remove the last element partial total. In order to keep the last element total, I'd prefer applying window functions instead of aggregations, and limit the output to the last row.
SET #current_time = CURRENT_TIMESTAMP();
WITH cte AS (
SELECT slot,
SUM(total) OVER(ORDER BY slot) AS total,
total AS rowtotal
FROM my_table
WHERE slot < #current_time
ORDER BY slot DESC
LIMIT 1
)
SELECT slot,
total - (30 - TIMESTAMPDIFF(MINUTE,
slot,
#current_time))
/30 * rowtotal AS total
FROM cte
Check the demo here.
Note1: Adding an index on the slot field is likely to boost this query performance.
Note2: If your query is running on millions of data, your timestamp may be likely to change during the query. You could store it into a variable before the query is run (or into another cte).
create an ondex in slot column btree as it is having high selectivity;
I have a database which shows the temperature in a certain location over time. The values are measured every 10 minutes as shown in the picture. Every location has an own ID called "Stationsnummer" (Station number).
What i want to do is calculate daily averages. So i need to write a query which calculates a daily average of the column "Temperatur Oberfläche".
With the query:
SELECT AVG (`Temperatur Oberfläche [°C]`)
FROM `temperatur oberfläche`
WHERE `Stationsnummer` LIKE '4900180611' AND `Datum` like '1998-11-10'
I get the average of one day. But in the end I wanna have something like this as a result:
Does someone has an idea how it can work?
Thanks a lot!
You can use GROUP BY for this:
select `datum`, avg(`Temperatur Oberfläche [°C]`)
from `temperatur oberfläche`
WHERE `Stationsnummer` = '4900180611'
group by `datum`;
Further if you want to find avg temp for all the stationsnummer for each day, you can include that too, like this:
select `Stationsnummer`, `datum`, avg(`Temperatur Oberfläche [°C]`)
from `temperatur oberfläche`
group by `Stationsnummer`, `datum`;
Sorry new to MYSQL, so not quite sure on the syntax and having trouble.
Trying to find the maximum and minimum temperatures for the current day in a certain location.
For example.
After the min and max (message) temperature for today (timeof) from the outside1 lcoation (locationmap)
table setup; (screenshot)
mqtt / temperatures
-id
-timeof <- DATETIME field
-message <-- this is the temperature field
-topic
-qos
-hardwareid
-locationmap
Just running this query inside MySQL workbench atm...
SELECT #min_temp:=MIN(message),#max_temp:=MAX(message),`timeof` FROM `mqtt`.`temperatures`;
SELECT * FROM `mqtt`.`temperatures` WHERE `timeof` >= CURDATE() AND (message=#min_temp OR message=#max_temp);
The above only returns a min/max but not for the current day and i think it is only returning the min.
Add a GROUP BY clause to group your results by location.
eg
SELECT locationmap, MIN(message) AS minTemp, MAX(message) AS maxTemp
FROM temperatures
GROUP BY locationmap;
That will give you a temperature range for each location. Alternatively, you can restrict the results to a single location without grouping:
SELECT MIN(message) AS minTemp, MAX(message) AS maxTemp
FROM temperatures
WHERE locationmap='kitchen';
I am looking to calculate moving averages over variable dates.
My database is structured:
id int
date date
price decimal
For example, I'd like to find out if the average price going back 19 days ever gets greater than the average price going back 40 days within the past 5 days. Each of those time periods is variable.
What I am getting stuck on is selecting a specific number of rows for subquery.
Select * from table
order by date
LIMIT 0 , 19
Knowing that there will only be 1 input per day, can I use the above as a subquery? After that the problem seems trivial....
if you only have one input per day you don't need id, date can be your primary id? Am i missing something? Then use select sum
SELECT SUM(price) AS totalPrice FROM table Order by date desc Limit (most recent date),(furthest back date)
totalPrice/(total days)
I may not understand your question
Yes you can use that as a sub-query like this:
SELECT
AVG(price)
FROM
(SELECT * FROM t ORDER BY date DESC LIMIT 10) AS t1;
This calculates the average price for the latest 10 rows.
see fiddle.
I have a table store_visits with the following structure:
store_visits:
store_name: string
visit_count: integer
visit_date: date
My goal is to create a query that for each store and a given date range, will calculate:
Average Number of Visits over the date range (currently using AVG(visit_count))
Whether store visits are increasing or decreasing
The relative rate of increase/decrease (1 to 4 scale where 1 = low rate, 4 = high rate)
The relative rate of increase/decrease in visits is for directional purpose only. It will always be a linear scale.
I've spent a day trying to construct the MySQL query to do this, and just can't get my head around it.
Any help would be greatly appreciated.
Thanks,
-Scott
Assuming you just want to compare the store visits in the first half of the date range to the second half, here's an example that spans the last 40 days using 2 sub-queries to get the counts for each range.
select
((endVisits + startVisits)/40) average,
(endVisits > startVisits) increasing,
((endVisits - startVisits)/(startVisits) * 100) percentChange
from
(select sum(visit_count) startVisits
from store_visit
where
visit_date > current_date - 40
and visit_date <= current_date - 20) startRange,
(select sum(visit_count) endVisits
from store_visit
where
visit_date > current_date - 20) endRange;
Notes
I don't know where the how you want to calculate your 1-4 increase amount, so I just made it a percentage and you can modify that to whatever logic you want. Also, you'll need to update the date ranges in the sub-queries as needed.
Edit: Just updated the average to ((endVisits + startVisits)/40) instead of ((endVisits + startVisits)/2). You could also use the avg function in your sub-queries and divide the sum of those by 2 to get the average over the whole period.