I have stored temperatures in a MySQL database. The table is called temperatures
. It contains, for example, the columns dtime
and temperature
. The first one is the time the temperature was measured (the column type is DATETIME
) and the latter, well, apparently the temperature (the type is FLOAT
).
At the moment I use the following query to fetch the temperatures in a certain period.
SELECT dtime, temperature
FROM temperatures
WHERE dtime BETWEEN "2012-11-15 00:00:00" AND "2012-11-30 23:59:59"
ORDER BY dtime DESC
I'd like to add the average temperature of the day in the results. I tried the following.
SELECT
dtime AS cPVM,
temperature,
(
SELECT AVG(temperature)
FROM temperatures
WHERE DATE(dtime) = DATE(cPVM)
) AS avg
FROM temperatures
WHERE dtime BETWEEN "2012-11-15 00:00:00" AND "2012-11-30 23:59:59"
ORDER BY dtime DESC
Works ok, but this is really, really slow. Fetching the results in that period takes about 5 seconds, when the first one (without the averages) is done in 0.03 seconds.
SELECT DATE(dtime), AVG(temperature)
FROM temperatures
WHERE DATE(dtime) BETWEEN "2012-11-15" AND "2012-11-30"
GROUP BY DATE(dtime)
ORDER BY dtime DESC
This one however is done in 0.04 seconds.
How do I fetch the average temperatures more efficiently?
Use a join instead of a correlated subquery:
SELECT dtime, temperature, avg_temperature
FROM temperatures
JOIN (
SELECT DATE(dtime) AS date_dtime, AVG(temperature) AS avg_temperature
FROM temperatures
WHERE dtime >= '2012-11-15' AND dtime < '2012-12-01'
GROUP BY DATE(dtime)
) AS avg_t
ON date_dtime = DATE(dtime)
WHERE dtime dtime >= '2012-11-15' AND dtime < '2012-12-01'
ORDER BY dtime DESC
Since your first query is very efficient already, let's use it as a starting point. Depending on the size of the result sets it produces, querying the results of your first query can still be very efficient.
Your third query also seems to run very efficiently, so you can fall back to that if my proposed query doesn't perform well enough. The reason I like it is because you can take the original query as a parameter of sorts (minus the ORDER BY
) and plug it into this one, which shows the average temperature from the date range of the original query:
SELECT
DATE(dtime) AS day_of_interest,
AVG(temperature) AS avg_temperature
FROM
(
-- Your first query is here, minus the ORDER BY clause
SELECT
dtime,
temperature
FROM
temperatures
WHERE
dtime BETWEEN "2012-11-15 00:00:00" AND "2012-11-30 23:59:59"
-- ORDER BY irrelevant inside subqueries, only slows you down
-- ORDER BY
-- dtime DESC
) AS temperatures_of_interest
GROUP BY
day_of_interest
ORDER BY
day_of_interest DESC
If this query runs "efficiently enough" ™ for you, then this could potentially be an easier solution to code up and automate than perhaps some others.
Hope this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.