#sql #sql-server
#sql #sql-сервер
Вопрос:
У меня есть таблица sql, которая хранит данные каждые 15 минут, но я хочу получать максимальное значение каждые 4 часа.
Это моя фактическая таблица:
---- ---- ---- -------------------------
| Id | F1 | F2 | timestamp |
---- ---- ---- -------------------------
| 1 | 24 | 30 | 2019-03-25 12:15:00.000 |
| 2 | 22 | 3 | 2019-03-25 12:30:00.000 |
| 3 | 2 | 4 | 2019-03-25 12:45:00.000 |
| 4 | 5 | 35 | 2019-03-25 13:00:00.000 |
| 5 | 18 | 23 | 2019-03-25 13:15:00.000 |
| ' | ' | ' | ' |
| 16 | 21 | 34 | 2019-03-25 16:00:00.000 |
---- ---- ---- -------------------------
Результат, который я ищу, это:
---- ---- ----
| Id | F1 | F2 |
---- ---- ----
| 1 | 24 | 35 |1st 4 Hours
---- ---- ----
| 2 | 35 | 25 |Next 4 Hours
---- ---- ----
Я использовал запрос
select max(F1) as F1,
max(F2) as F2
from table
where timestamp>='2019/3/26 12:00:01'
and timestamp<='2019/3/26 16:00:01'
и он возвращает значение первых 4 часов, но когда я увеличиваю временную метку с 4 часов до 8 часов, это все равно даст мне 1 максимальное значение, а не 2 за 4 часа.
Я пытался использовать предложение group by, но не смог получить ожидаемый результат.
Комментарии:
1. это за 4 часа, в час, за 24-часовой период, например 0, 4, 8 ,12,16,20:00 или каждые четыре часа с любой заданной начальной точки? например 1:24,5:24,9:24,13:24…
2. … и заканчивается ли диапазон дат (например, вы указываете даты начала / окончания, хотите только 24 часа и т.д.). Говорить «это моя таблица» здорово, когда вы показываете нам 6 строк. Но, несомненно, ваша таблица со временем будет увеличиваться.
3. @TJB Я регистрирую данные каждые 15 минут, поэтому данные будут в очень специфическом формате: 2:00, 2:15,2:30,3:00, 3:15. И мой начальный день был бы первым днем месяца, а конечный день был бы последним днем месяца. Данные не будут иметь никаких других временных меток, таких как 1: 24 и так далее.
4. @AaronBertrand Моими датами начала и окончания будут первый и последний день месяца. Я знаю, что таблица будет расти, и я учел это в своей архитектуре.
Ответ №1:
Это должно сработать
SELECT Max(f1),
Max(f2), datepart(hh,timestamp), convert(date,timestamp)
FROM TABLE
WHERE datepart(hh,timestamp)%4 = 0
AND timestamp>='2019/3/26 12:00:01'
AND timestamp<='2019/3/26 16:00:01'
GROUP BY datepart(hh,timestamp), convert(date,timestamp)
ORDER BY convert(date,timestamp) asc
Комментарии:
1. Еще один
WHERE
послеORDER BY
? Это недопустимый синтаксис.WHERE
Идет после предложенийFROM
andON
и передGROUP BY
, нигде больше, и их не может быть два.2. @MatthewEvans Это работает, если мой диапазон дат равен 1 дню, но если я увеличу диапазон дат до месяца, который я ищу, то это просто даст мне только 6 значений.
3. @MatthewEvans Это очень близко, но я получаю результаты, отсортированные по часам, а не по дате. Итак, я хотел 2019-3-26 0,2019-3-26 4,2019-3-26 8……. но то, что я получаю, это 2019-3-26 0,2019-3-27 0,2019-3-28 0……… Надеюсь, это имеет смысл.
4. упорядочено по дате, затем по 4 часовым периодам
5. @MatthewEvans Я удалил часть даты (hh, временную метку) из предложения order by и получил то, что искал. Спасибо за помощь. Ценю это.
Ответ №2:
Вот относительно простой метод:
select convert(date, timestamp) as dte,
(datepart(hour, timestamp) / 4) * 4 as hour,
max(F1) as F1,
max(F2) as F2
from table
group by convert(date, timestamp), (datepart(hour, timestamp) / 4) * 4;
Это позволяет распределить дату и час по отдельным столбцам; вы можете использовать dateadd()
, чтобы поместить их в один столбец.
Ответ №3:
Попробуйте этот запрос:
declare @startingDatetime datetime = '2017-10-04 12:00:00';
select grp, max(F1) F1, max(F2) F2
from (
select datediff(hour, @startingDatetime, [timestamp]) / 4 grp, *
from MyTable
where [timestamp] > @startingDatetime
) a group by grp
Комментарии:
1. Что такое startTime? Это столбец временной метки?