Сгруппируйте DateTime с интервалами в 5, 15, 30 и 60 минут. - PullRequest
14 голосов
/ 22 марта 2012

Я пытаюсь сгруппировать некоторые записи в 5-, 15-, 30- и 60-минутные интервалы:

SELECT AVG(value) as "AvgValue",
sample_date/(5*60) as "TimeFive"
FROM DATA
WHERE id = 123 AND sample_date >= 3/21/2012

Я хочу выполнить несколько запросов, каждый из которых сгруппировал бы мои средние значения в желаемыевремя приращения.Таким образом, 5-минутный запрос будет возвращать результаты, подобные этому:

AvgValue  TimeFive
6.90      1995-01-01 00:05:00
7.15      1995-01-01 00:10:00
8.25      1995-01-01 00:15:00

30-минутный запрос приведет к следующему:

AvgValue  TimeThirty 
6.95      1995-01-01 00:30:00
7.40      1995-01-01 01:00:00

Столбец datetime находится в yyyy-mm-dd hh:mm:ssформат

Я получаю неявные ошибки преобразования моего столбца datetime.Любая помощь очень ценится!

Ответы [ 3 ]

18 голосов
/ 22 марта 2012

Использование

datediff(minute, '1990-01-01T00:00:00', yourDatetime)

даст вам количество минут с 1990-1-1 (вы можете использовать желаемую базовую дату).

Затем вы можете разделить на 5, 1530 или 60, и сгруппировать по результату этого деления.Я проверял, что это будет оцениваться как целочисленное деление, поэтому вы получите целое число, которое вы можете использовать для группировки.

т.е.

group by datediff(minute, '1990-01-01T00:00:00', yourDatetime) /5

ОБНОВЛЕНИЕ Поскольку исходный вопрос был отредактирован так, чтобы после группировки данные отображались в формате даты и времени, я добавил этот простой запрос, который будет выполнять то, что хочет OP:

-- This convert the period to date-time format
SELECT 
    -- note the 5, the "minute", and the starting point to convert the 
    -- period back to original time
    DATEADD(minute, AP.FiveMinutesPeriod * 5, '2010-01-01T00:00:00') AS Period,
    AP.AvgValue
FROM
    -- this groups by the period and gets the average
    (SELECT
        P.FiveMinutesPeriod,
        AVG(P.Value) AS AvgValue
    FROM
        -- This calculates the period (five minutes in this instance)
        (SELECT 
            -- note the division by 5 and the "minute" to build the 5 minute periods
            -- the '2010-01-01T00:00:00' is the starting point for the periods
            datediff(minute, '2010-01-01T00:00:00', T.Time)/5 AS FiveMinutesPeriod,
            T.Value
        FROM Test T) AS P
    GROUP BY P.FiveMinutesPeriod) AP

ПРИМЕЧАНИЕ: я разделил это на 3 подзапроса для ясности.Вы должны прочитать это изнутри.Конечно, его можно записать в виде одного компактного запроса

ПРИМЕЧАНИЕ: если вы измените период и начальную дату-время, вы можете получить любой необходимый интервал, например, недели, начиная сс данного дня, или что вам нужно

Если вы хотите сгенерировать тестовые данные для этого запроса, используйте это:

CREATE TABLE Test
( Id INT IDENTITY PRIMARY KEY,
Time DATETIME,
Value FLOAT)

INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:00:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:03:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:04:45', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:07:21', 20)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:10:25', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:11:22', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:14:47', 30)

Результат выполнения запроса таков:

Period                     AvgValue
2012-03-22 00:00:00.000    10
2012-03-22 00:05:00.000    20
2012-03-22 00:10:00.000    30
8 голосов
/ 21 марта 2016

Опираясь на ответ @ JotaBe (к которому я не могу комментировать - иначе я бы сделал это), вы также можете попробовать что-то подобное, не требующее подзапроса.

 SELECT 
    AVG(value) AS 'AvgValue',

    -- Add the rounded seconds back onto epoch to get rounded time
    DATEADD(
        MINUTE,
        (DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30) * 30,
        '1990-01-01T00:00:00'
    )      AS 'TimeThirty'

 FROM YourTable
 -- WHERE your_date > some max lookback period
 GROUP BY
    (DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30)

Это изменение удаляет временные таблицыи подзапросы.Он использует ту же самую базовую логику для группировки по 30-минутным интервалам, но при представлении данных обратно как части результата я просто обращаюсь к вычислению интервала, чтобы получить округленную дату и время.

6 голосов
/ 30 сентября 2014

Итак, если вы гуглили это, но вам нужно сделать это в mysql, что было в моем случае:

В MySQL вы можете сделать

GROUP BY
CONCAT(
    DATE_FORMAT(`timestamp`,'%m-%d-%Y %H:'),
    FLOOR(DATE_FORMAT(`timestamp`,'%i')/5)*5
)
...