简体   繁体   中英

How to get the maximum and minimum values in each group as well as their times?

Let's say I have a table MyTable with the columns Id, NumericValue and UTCTimestamp. I'm trying to group the results of my table MyTable by the hour of their timestamp and return the maximum NumericValuefor each group with its associated timestamp as well as the minimum NumericValue for each group with its associated timestamp value.

For now, I'm able to achieve the first part of my problem with the following query:

SELECT 
    HOUR(t.UTCTimestamp) AS `Hour`, 
    t.NumericValue AS MaximumValue,
    t.UTCTimestamp AS MaximumValueTime
FROM MyTable t
INNER JOIN (
    SELECT HOUR(t2.UTCTimestamp) AS `Hour`, MAX(t2.NumericValue) AS NumericValue
    FROM MyTable t2
    GROUP BY HOUR(t2.UTCTimestamp)
) maxNumericValue ON HOUR(t.UTCTimestamp) = maxNumericValue.`Hour` AND t.NumericValue = maxNumericValue.NumericValue
GROUP BY HOUR(t.UTCTimestamp);

Which was inspired by this answer .

Here's an MVCE .

How could I also show the minimum value for each group as well as the timestamp associated to it?

Starting from MySQL 8.0 you could use ROW_NUMBER :

WITH cte AS (
  SELECT *,ROW_NUMBER() OVER(PARTITION BY HOUR(UTCTimestamp) 
                              ORDER BY UTCTimestamp ASC)  AS rn
          ,ROW_NUMBER() OVER(PARTITION BY HOUR(UTCTimestamp) 
                              ORDER BY UTCTimestamp DESC) AS rn2
  FROM MyTable
)
SELECT HOUR(c1.UTCTimestamp),
     c1.ID, c1.NumericValue, c1.UTCTimestamp,  -- min row
     c2.ID, c2.NumericValue, c2.UTCTimestamp   -- max row
FROM cte c1
JOIN cte c2
  ON HOUR(c1.UTCTimestamp) = HOUR(c2.UTCTimestamp)
  AND c1.rn=1
  AND c2.rn2=1
ORDER BY HOUR(c1.UTCTimestamp) ASC;

DBFiddle Demo

Apply the same technique but with minimum:

select a.*, b.MinimumValueTime from (
SELECT 
    HOUR(t.UTCTimestamp) AS `Hour`, 
    t.NumericValue AS MaximumValue,
    t.UTCTimestamp AS MaximumValueTime
FROM MyTable t
INNER JOIN (
    SELECT HOUR(t2.UTCTimestamp) AS `Hour`, MAX(t2.NumericValue) AS NumericValue
    FROM MyTable t2
    GROUP BY HOUR(t2.UTCTimestamp)
) maxNumericValue ON HOUR(t.UTCTimestamp) = maxNumericValue.`Hour` AND t.NumericValue = maxNumericValue.NumericValue
GROUP BY HOUR(t.UTCTimestamp))a
join
(
SELECT 
    HOUR(t.UTCTimestamp) AS `Hour`, 
    t.NumericValue AS MinimumValue,
    t.UTCTimestamp AS MinimumValueTime
FROM MyTable t
INNER JOIN (
    SELECT HOUR(t2.UTCTimestamp) AS `Hour`, MIN(t2.NumericValue) AS NumericValue
    FROM MyTable t2
    GROUP BY HOUR(t2.UTCTimestamp)
) minNumericValue ON HOUR(t.UTCTimestamp) = minNumericValue.`Hour` AND t.NumericValue = minNumericValue.NumericValue
GROUP BY HOUR(t.UTCTimestamp))b on a.hour=b.hour

You can join to MyTable twice (and only use one aggregating subquery)

SELECT bounds.`Hour`
    , minT.NumericValue AS MinValue
    , minT.UTCTimestamp AS MinTime
    , maxT.NumericValue AS MaximumValue
    , maxT.UTCTimestamp AS MaximumValueTime
FROM (
    SELECT HOUR(t2.UTCTimestamp) AS `Hour`
         , MAX(t2.NumericValue) AS maxValue
         , MIN(t2.NumericValue) AS minValue
    FROM MyTable t2
    GROUP BY HOUR(t2.UTCTimestamp)
) bounds 
LEFT JOIN MyTable minT ON bounds.`Hour` = HOUR(minT.UTCTimestamp)
   AND bounds.minValue = minT.NumericValue
LEFT JOIN MyTable maxT ON bounds.`Hour` = HOUR(maxT.UTCTimestamp)
   AND bounds.maxValue = maxT.NumericValue
;

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM