#mysql #mariadb #max
#mysql #mariadb #макс
Вопрос:
РЕДАКТИРОВАТЬ: я переработал вопрос и пример, поскольку предыдущий пример включал только один город.
Я ищу, чтобы найти одну строку для каждого города с наивысшим значением max_wind ИЛИ max_gust.
Вот базовый запрос (http://sqlfiddle.com /#!9/42f63e/2):
SELECT *
FROM high_wind
WHERE timestamp > NOW() - INTERVAL 72 HOUR;
------ ----------- ---------- ---------- ---------------------
| hid | city | max_wind | max_gust | timestamp |
------ ----------- ---------- ---------- ---------------------
| 4784 | Vancouver | 63 | 90 | 2021-01-13 08:26:00 |
| 4785 | Vancouver | 54 | 71 | 2021-01-13 08:40:00 |
| 4786 | Calgary | 52 | 71 | 2021-01-13 15:35:00 |
| 4787 | Calgary | 57 | 79 | 2021-01-13 17:53:00 |
| 4788 | Calgary | 67 | 86 | 2021-01-13 18:14:00 |
| 4789 | Calgary | 70 | 84 | 2021-01-13 18:40:00 |
| 4790 | Calgary | 51 | 86 | 2021-01-13 19:00:00 |
| 4791 | Calgary | 55 | 75 | 2021-01-13 20:00:00 |
| 4792 | Saskatoon | 66 | 81 | 2021-01-14 00:18:00 |
| 4793 | Saskatoon | 53 | 73 | 2021-01-14 01:26:00 |
| 4794 | Saskatoon | 59 | 77 | 2021-01-14 01:44:00 |
| 4795 | Saskatoon | 72 | 91 | 2021-01-14 02:00:00 |
| 4796 | Saskatoon | 77 | 103 | 2021-01-14 03:00:00 |
| 4797 | Saskatoon | 52 | 65 | 2021-01-14 05:00:00 |
| 4798 | Saskatoon | 57 | 68 | 2021-01-14 06:13:00 |
| 4799 | Saskatoon | 50 | 64 | 2021-01-14 09:00:00 |
| 4800 | Saskatoon | 51 | 61 | 2021-01-14 15:00:00 |
| 4801 | Resolute | 51 | | 2021-01-15 04:00:00 |
------ ----------- ---------- ---------- ---------------------
18 rows in set (0.004 sec)
Из приведенного выше примера данных это будет конечный предполагаемый результат:
------ ----------- ---------- ---------- ---------------------
| hid | city | max_wind | max_gust | timestamp |
------ ----------- ---------- ---------- ---------------------
| 4784 | Vancouver | 63 | 90 | 2021-01-13 08:26:00 |
| 4788 | Calgary | 67 | 86 | 2021-01-13 18:14:00 |
| 4796 | Saskatoon | 77 | 103 | 2021-01-14 03:00:00 |
| 4801 | Resolute | 51 | | 2021-01-15 04:00:00 |
------ ----------- ---------- ---------- ---------------------
Я думал, что нашел решение со следующим запросом ВНУТРЕННЕГО СОЕДИНЕНИЯ, однако результаты неоднозначны. Здесь он правильно выдал два результата, но пропустил два других.
SELECT *
FROM high_wind a
JOIN
( SELECT city
, MAX(max_wind) max_wind
, MAX(max_gust) max_gust
FROM high_wind
WHERE timestamp >= NOW() - INTERVAL 72 HOUR
GROUP
BY city
) b
ON a.city = b.city
AND a.max_wind = b.max_wind
AND a.max_gust = b.max_gust
WHERE timestamp >= NOW() - INTERVAL 72 HOUR;
------ ----------- ---------- ---------- ---------------------
| hid | city | max_wind | max_gust | timestamp |
------ ----------- ---------- ---------- ---------------------
| 4784 | Vancouver | 63 | 90 | 2021-01-13 08:26:00 |
| 4801 | Resolute | 51 | | 2021-01-15 04:00:00 |
------ ----------- ---------- ---------- ---------------------
2 rows in set (0.006 sec)
Комментарии:
1. Неверно говорить, что город / дата-время с наибольшей скоростью ветра совпадает с городом / датой-временем с наибольшим порывом. вам нужно идентифицировать оба, а затем присоединиться к данным, используя distinct, если они совпадают с городом / датой / временем
2. Добавлено: sqlfiddle.com /#!9/88365d/7
Ответ №1:
SELECT hw.*
FROM (
SELECT MAX(wind) AS max_wind,
MAX(gust) AS max_gust
FROM high_wind
WHERE ...
) AS mx
JOIN high_wind AS hw ON ( hw.wind = mx.max_wind
OR hw.gust = mx.max_gust )
WHERE ...
ORDER BY ...
Вы можете получить 1 строку, если максимальные значения относятся к одному и тому же городу и времени.
Возможно, у вас больше 2 строк, если для MAX (..) одинаковые значения для разных городов или времени.
Если у вас миллион строк в high_wind, мы можем обсудить индексы, чтобы повысить производительность. Для моего запроса потребуется 2 полных сканирования таблицы, если вы не добавите INDEX(wind)
и INDEX(gust)
. Но если вам нужно что-то в WHERE
(например, ограничение по провинции или диапазон дат), этих индексов будет недостаточно.
Для простого WHERE timestamp > ...
добавления
INDEX(timestamp)
INDEX(wind, timestamp)
INDEX(gust, timestamp)
Еще
Не использовать VARCHAR
для числовых (или дат) значений:
`max_wind` varchar(20) DEFAULT NULL,
При этом «102» меньше, чем «99»!
Комментарии:
1. Спасибо за пример! Цель состоит в том, чтобы запускать этот запрос каждые X часов с диапазоном предыдущих X часов (т. Е. NOW() — ИНТЕРВАЛ 8 ЧАСОВ).
2. @skyblaster — Если в час «много» записей, я бы подтолкнул вас к созданию и ведению «сводной таблицы». Но, похоже, очень мало чтений за 8 (или 12 или 13) часов?
3. это правильно. Существует менее 50 городов, которые отслеживаются на «почасовой» основе, и в эту таблицу записываются только ветры, превышающие 50 км / ч.
4. @skyblaster — Значит, могут быть часы, даже дни, без строк в таблице? Это может привести к дополнительному коду для распознавания этой ситуации и доставки
NULL
или чего-то еще.5. Я переработал вопрос и чувствую, что становлюсь ближе. Пожалуйста, посмотрите sqlfiddle.com /#!9/42f63e/15