Оператор SQL для получения записей с max (свойством) группы - PullRequest
1 голос
/ 31 января 2012

Учитывая следующую таблицу

select rv, mv, datetime, rawv from mytable where datetime > '2012-01-30';
+------+------+---------------------+------+
| rv   | mv   | datetime            | rawv |
+------+------+---------------------+------+
|    5 |   81 | 2012-01-31 07:00:00 |    1 |
|    5 |   81 | 2012-01-31 07:01:00 |    2 |
|    5 |   82 | 2012-01-31 07:00:00 |    3 |
|    5 |   82 | 2012-01-31 07:01:00 |    4 |
|    5 |   83 | 2012-01-31 08:00:00 |    5 |
|    5 |   83 | 2012-01-31 08:01:00 |    6 |
+------+------+---------------------+------+

Я ищу SQL-оператор, который предоставляет записи с максимальным значением datetime для каждой группы rv, mv.Результат должен выглядеть следующим образом:

+------+------+---------------------+------+
| rv   | mv   | max(datetime)       | rawv |
+------+------+---------------------+------+
|    5 |   81 | 2012-01-31 07:01:00 |    2 |
|    5 |   82 | 2012-01-31 07:01:00 |    4 |
|    5 |   83 | 2012-01-31 08:01:00 |    6 |
+------+------+---------------------+------+

Знаете ли вы такое утверждение?

То, что я пробовал до сих пор, заключается в следующем, но, как вы можете видеть, я получаю неправильные результаты:

select rv, mv, max(datetime), rawv from mytable
where mv in (81,82,83)
group by rv, mv;
+------+------+---------------------+------+
| rv   | mv   | max(datetime)       | rawv |
+------+------+---------------------+------+
|    5 |   81 | 2012-01-31 07:01:00 |    0 |
|    5 |   82 | 2012-01-31 07:01:00 |    0 |
|    5 |   83 | 2012-01-31 08:01:00 |    5 |
+------+------+---------------------+------+
3 rows in set (0.72 sec)

и

select rv, mv, datetime, rawv from mytable
where mp_nb in (81,82,83)
and datetime=(select max(datetime) from met_value);

+------+------+---------------------+------+
| rv   | mv   | datetime            | rawv |
+------+------+---------------------+------+
|    5 |   83 | 2012-01-31 08:01:00 |    6 |
+------+------+---------------------+------+

Ответы [ 3 ]

4 голосов
/ 31 января 2012

Попробуйте этот запрос -

SELECT t1.rv, t1.mv, t1.datetime, t1.rawv FROM mytable t1
  JOIN (SELECT rv, mv, MAX(datetime) datetime FROM mytable GROUP BY rv, mv) t2
    ON t1.rv = t2.rv AND t1.mv = t2.mv AND t1.datetime = t2.datetime
1 голос
/ 31 января 2012

Это довольно распространенный вопрос, и вы найдете похожие вопросы / ответы в теге «max-n-per-group» в переполнении стека.

Обычный способ сделать это - присоединить mytable к себе с помощью ЛЕВОГО СОЕДИНЕНИЯ:

SELECT a.rv, a.mv, a.datetime, a.rawv
FROM mytable a
LEFT JOIN mytable b
 ON a.rv=b.rv AND a.mv=b.mv
 AND a.datetime < b.datetime
WHERE a.mv IN (81,82,83)
AND b.datetime IS NULL;

Общая форма этого запроса:

SELECT a.[colnames I want]
FROM mytable a
LEFT JOIN mytable b
 ON a.[colnames to GROUP BY] = b.[colnames to GROUP BY]
 AND a.[colname I want MAX of] < b.[colname I want MAX of]
WHERE b.[colname I want MAX of] IS NULL
[and any other where conditions]

Он в основном присоединяет таблицу к себе в ваших столбцах mv и rv и создает пары datetime в каждой группе mv, rv, так что a меньше b.

Если в такой строке есть строка, для которой в b нет большего значения (т. Е. B.datetime IS NULL), то у вас есть именно максимум для этой группы.

0 голосов
/ 31 января 2012

Вы не можете смешивать агрегированные и неагрегированные столбцы таким образом.

Из вашего набора данных я заметил, что rawv также увеличивается со временем. Если это правда, вы также можете MAX это.

select rv, mv, max(datetime), max(rawv)
from mytable
where mv in (81,82,83)
group by rv, mv;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...