如何获得每组中的最大值和最小值以及它们的时间?

时间:2018-05-03 17:23:55

标签: mysql sql greatest-n-per-group mysql-5.6

假设我有一个表MyTable,其中包含Id,NumericValue和UTCTimestamp列。我试图将我的表MyTable的结果按其时间戳的小时分组,并返回每个组的最大NumericValue及其关联的时间戳以及每个组的最小NumericValue及其关联的时间戳值。

目前,我可以使用以下查询解决问题的第一部分:

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

受到this answer的启发。

Here's an MVCE

我怎样才能显示每个组的最小值以及与之关联的时间戳?

3 个答案:

答案 0 :(得分:2)

从MySQL 8.0开始,您可以使用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

答案 1 :(得分:1)

应用相同的技术,但最少:

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

答案 2 :(得分:1)

您可以加入MyTable两次(并且只使用一个聚合子查询)

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
;