Min max query for temperatures on a day - mysql

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';

Related

How to get the number of registers by month and date

I have rows of user data. I store the createDate, which is the timestamp in milliseconds when the user registered. I want to get the total number of registrations per month. When I try to do that, I don't get any rows returned. Here's the query I'm using
SELECT COUNT(*) FROM users WHERE YEAR(createDate) = 2023 GROUP BY MONTH(createDate)
createDate is BIGINT and is the date in milliseconds
I guess your createDate column is defined as TIMESTAMP(3), to get millisecond resolution. LAST_DAY() comes in handy here.
Try this:
SELECT COUNT(*), LAST_DAY(createDate) month_ending
FROM users
WHERE createDate >= '2023-01-01'
AND createDate < '2024-01-01'
GROUP BY LAST_DAY(createDate)
The date range test I use for getting the dates in a single year is sargable. That is, it can be accelerated by an index on createDate, where YEAR(createDate) cannot be.
This approach generates a useful result set if you run it on a multi-year date range.
But, if your result set is empty (has no rows), the result set from this query will be too. That might mean:
your table has no dates in that range, or
your createDate data type is something other than TIMESTAMP or DATETIME. (You didn't show us the table definition.)
It sounds like you need to convert to/from unix time:
SELECT COUNT(*), LAST_DAY(FROM_UNIXTIME(createDate/1000)) month_ending
FROM users
WHERE createDate >= UNIX_TIMESTAMP('2023-01-01') * 1000
AND createDate < UNIX_TIMESTAMP('2024-01-01') * 1000
GROUP BY month_ending

MySQL - group by interval query optimisation

Some background first. We have a MySQL database with a "live currency" table. We use an API to pull the latest currency values for different currencies, every 5 seconds. The table currently has over 8 million rows.
Structure of the table is as follows:
id (INT 11 PK)
currency (VARCHAR 8)
value (DECIMAL
timestamp (TIMESTAMP)
Now we are trying to use this table to plot the data on a graph. We are going to have various different graphs, e.g: Live, Hourly, Daily, Weekly, Monthly.
I'm having a bit of trouble with the query. Using the Weekly graph as an example, I want to output data from the last 7 days, in 15 minute intervals. So here is how I have attempted it:
SELECT *
FROM currency_data
WHERE ((currency = 'GBP')) AND (timestamp > '2017-09-20 12:29:09')
GROUP BY UNIX_TIMESTAMP(timestamp) DIV (15 * 60)
ORDER BY id DESC
This outputs the data I want, but the query is extremely slow. I have a feeling the GROUP BY clause is the cause.
Also BTW I have switched off the sql mode 'ONLY_FULL_GROUP_BY' as it was forcing me to group by id as well, which was returning incorrect results.
Does anyone know of a better way of doing this query which will reduce the time taken to run the query?
You may want to create summary tables for each of the graphs you want to do.
If your data really is coming every 5 seconds, you can attempt something like:
SELECT *
FROM currency_data cd
WHERE currency = 'GBP' AND
timestamp > '2017-09-20 12:29:09' AND
UNIX_TIMESTAMP(timestamp) MOD (15 * 60) BETWEEN 0 AND 4
ORDER BY id DESC;
For both this query and your original query, you want an index on currency_data(currency, timestamp, id).

How to update rows which have the max value per day?

I have a MySQL table 'weather_data' which has the following fields:
id
temperature
time
max_temperature
It gets updated every 15 mins.
With the following MySQL command I can see the max temperature values per day:
SELECT MAX(temperature) FROM 'weather_data' GROUP BY DAY(time)
What I want is a MySQL command which goes through all my data, finds the max temperature per day and on each of that row updates the max_temperature field with the temperature on that time.
So if i have seven days of data I want to update 7 rows with max_temperature.
Is this possible?
First, I think you should store frequent temp and max temp in two separate tables.
Second, if you still prefer your schema, you can do something like this:
UPDATE weather_data
INNER JOIN (
SELECT MAX(temperature) as temperature, DAY(time) as date
FROM weather_data GROUP BY DAY(time)
) max_temp
ON max_temp.date = DAY(time)
SET weather_data.max_temperature = max_temp.temperature
Edit:
If you would like to use the two tables approach, I'd suggest you have the following tables:
weather_data:
id
temperature
time
max_daily_temperature:
id
max_temperature
date
As for inserting: I think you already have taken care of weather_data, but for max_daily_temperature, it would be something like this:
INSERT INTO max_daily_temperature
SELECT DATE(time), MAX(temperature)
FROM weather_data
WHERE DATE(time) = '2017-08-30'
and for update:
UPDATE max_daily_temperature
SET max_temperature = (
SELECT MAX(temperature)
FROM weather_data
WHERE DATE(time) = '2017-08-30'
)
WHERE date = '2017-08-30'
If that is what you are looking fore, don't forget to mark the answer as a solution.

MYSQL Query to Select Max Value in a Column only from Current Date

I have the following table:
I want to run a query to select the maximum value from the 'MaxWind' column but only return the result from today's date.
You can probably see where I'm going here. I want the maximum windspeed for the current date. I would like to return what the value was and also the time it occurred.
This would work for "today":
select max(maxwind) from weather where stamp > '2015=10=16 0:00'
For each day, you could use CURDATE:
select max(maxwind) from weather where stamp >= CURDATE()

How to get the average price for the X most recent rows based on date?

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.