I am trying to write a MySQL query for graphing purposes, the graph is for a single column but at different times of the day.
I have a table which is measuring the State of Charge of a large battery and I want to produce a table for graphing where I can get the SoC at roughly 2am and 7am
This is one SELECT that I am using for the 2am
SELECT luxpower.`Date_MySQL`,
luxpower.`soc`
FROM luxpower
WHERE luxpower.`Minutes_Since_Midnight` <= 120
GROUP BY luxpower.`Date_MySQL`
and this is the SELECT I am suinf for 7am
SELECT luxpower.`Date_MySQL`,
luxpower.`soc`
FROM luxpower
WHERE luxpower.`Minutes_Since_Midnight` <= 420
GROUP BY luxpower.`Date_MySQL`
What I would like is the combine into a single query with soc as 2 different alias, something like this (which does not work)
SELECT luxpower.`Date_MySQL`,
luxpower.`soc` as socama (FROM luxpower WHERE luxpower.`Minutes_Since_Midnight` <= 120 GROUP BY luxpower.`Date_MySQL`)
AND
SELECT luxpower.`Date_MySQL`,
luxpower.`soc` as socamb (FROM luxpower WHERE luxpower.`Minutes_Since_Midnight` <= 420 GROUP BY luxpower.`Date_MySQL`)
I am a recordset to be like
Date_MySQL,socama ,socamab
2024-06-01,10,7
2024-06-02,15,17
2024-06-03,23,44
2024-06-04,10,32
Thanks
2
Answers
You can achieve this by having two sub queries then join them.
The first query checks where Minutes_Since_Midnight is less or equal to 2am while the second checks where it is less or equal to 7am.
You can read more here https://dev.mysql.com/doc/refman/8.4/en/all-subqueries.html
Your two queries should be raising errors as
soc
is not in the GROUP BY clause or in an aggregate function. The fact that they are "working" means you haveONLY_FULL_GROUP_BY
disabled, which is a bad thing. Please read MySQL Handling of GROUP BY, particularly the bit explaining nondeterministic results.Sample data
The currently accepted answer would output:
These are incorrect, as it is simply returning the maximum
soc
in the given group, as opposed to thesoc
for the maximumMinutes_Since_Midnight
in the group.There are lots of ways to achieve this, one being to use correlated subqueries in the select list:
Outputs:
Another way is to use conditional aggregation to get the two max times (<= 120 and <= 420) and then use them to join back to retrieve the
soc
:Same output as previous query.
You could also achieve the same using the
ROW_NUMBER()
window function and then conditional aggregation to pivot the result:Same output again.
Here’s a db<>fiddle.