web-dev-qa-db-ja.com

DateTimeを5、15、30、60分の間隔にグループ化

一部のレコードを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列の暗黙的な変換エラーが発生します。どんな助けでも大歓迎です!

15
jrubengb

使用する

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

1990-1-1以降の分数が表示されます(目的の基準日を使用できます)。

次に、5、15、30、または60で除算し、この除算の結果でグループ化できます。私はそれが整数除算として評価されるので、グループ化に使用できる整数を取得することを確認しました。

つまり.

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

[〜#〜] update [〜#〜]元の質問が編集され、グループ化後にデータを日時形式で表示する必要があるため、この簡単なクエリを追加しました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
18
JotaBe

@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分間隔でグループ化するために使用しますが、結果の一部としてデータを返す場合、間隔の計算を逆にして丸められた日付と時刻を取得します。

8
DJ Sipe

それで、あなたがこれをググったが、mysqlでそれをする必要がある場合、それは私の場合でした:

MySQLでできること

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