将DateTime分组为5,15,30和60分钟

jru*_*ngb 14 sql sql-server aggregate-functions sql-server-2008

我试图将一些记录分为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
Run Code Online (Sandbox Code Playgroud)

我想运行几个查询,每个查询将我的平均值分组为所需的时间增量.所以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
Run Code Online (Sandbox Code Playgroud)

30分钟的查询将导致:

AvgValue  TimeThirty 
6.95      1995-01-01 00:30:00
7.40      1995-01-01 01:00:00
Run Code Online (Sandbox Code Playgroud)

datetime列的yyyy-mm-dd hh:mm:ss格式

我收到了我的datetime列的隐式转换错误.任何帮助深表感谢!

Jot*_*aBe 18

运用

datediff(minute, '1990-01-01T00:00:00', yourDatetime)
Run Code Online (Sandbox Code Playgroud)

将给你自1990-1-1以来的分钟数(你可以使用所需的基准日期).

然后你可以除以5,15,30或60,并按此除法的结果分组.我已经将它评估为整数除法,因此您将得到一个可用于分组的整数.

group by datediff(minute, '1990-01-01T00:00:00', yourDatetime) /5
Run Code Online (Sandbox Code Playgroud)

更新由于原始问题被编辑为要求在分组后以日期时间格式显示数据,我添加了这个简单的查询,它将执行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
Run Code Online (Sandbox Code Playgroud)

注意:为了清楚起见,我将其划分为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)
Run Code Online (Sandbox Code Playgroud)

执行查询的结果如下:

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
Run Code Online (Sandbox Code Playgroud)


DJ *_*ipe 8

基于@ 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)
Run Code Online (Sandbox Code Playgroud)

此更改将删除临时表和子查询.它使用相同的核心逻辑以30分钟的间隔进行分组,但是当作为结果的一部分呈现数据时,我只是反转间隔计算以获得舍入的日期和时间.


chi*_*NUT 7

所以,万一你用google搜索,但你需要在mysql中这样做,这是我的情况:

在MySQL中你可以做到

GROUP BY
CONCAT(
    DATE_FORMAT(`timestamp`,'%m-%d-%Y %H:'),
    FLOOR(DATE_FORMAT(`timestamp`,'%i')/5)*5
)
Run Code Online (Sandbox Code Playgroud)

  • 问题是关于`sql-server`,但它也用普通的`sql`标记,所以包括所有的味道 (4认同)