按时间间隔对数据进行分组

时间:2013-02-08 20:46:35

标签: sql oracle time grouping intervals

我想按时间间隔对表中的数据进行分组。该表保存包含用户ID,项目名称,型号,数量,活动日期等的订单信息。现在,我想按时间间隔对此数据进行分组。时间间隔可以是5分钟,10分钟,15等等。此外,查询应仅返回在该5分钟间隔内多次发出命令的那些用户(所有列数据)。是否可以在一个SQL查询中实现此目的?我使用Oracle。

谢谢

修改

示例数据

**userid    item name    model      quantity   order date**
abc calculator   cdm83ss    1      02-FEB-2013 09:20:13     
abc alarm clock  actp001    1      02-FEB-2013 09:26:22
yyy iPhone       iP4    1      02-FEB-2013 09:28:14
abc alarm clock  actz321    2      02-FEB-2013 09:30:00
zzz backpack     bp344tk    1      04-FEB-2013 13:15:00
zzz backpack     bp234zz    2      04-FEB-2013 13:19:32
zzz camera       cm234  1      04-FEB-2013 13:20:22 
ttt tv       fs45yup    1      04-FEB-2013 13:28:19

我希望得到:

**userid    item name    model      quantity   order date**
abc         calculator   cdm83ss    1      02-FEB-2013 09:20:13     
abc         alarm clock  actp001    1      02-FEB-2013 09:26:22
abc         alarm clock  actz321    2      02-FEB-2013 09:30:00
zzz         backpack     bp344tk    1      04-FEB-2013 13:15:00
zzz         backpack     bp234zz    2      04-FEB-2013 13:19:32
zzz         camera       cm234  1      04-FEB-2013 13:20:22 

2 个答案:

答案 0 :(得分:7)

是。据推测,您希望将结果视为日期时间值。这需要一些日期时间算法。基本上,获取自午夜以来的分钟数,除以分钟数再乘以(向下舍入)。然后在午夜时间加回:

select t.*
from (select t.*,
             count(*) over (partition by userid, interval) as CntInInterval
      from (select trunc(orderdate)+
                   (floor(((orderdate - trunc(orderdate))*24*60)/10)*10)/(24*60) as interval, t.*
            from t
           ) t
     ) t
where cntInInterval > 1

要按时间间隔分组,您可以使用:

      select interval, count(*)
      from (select trunc(orderdate)+floor(((orderdate - trunc(orderdate))*24*60)/10)*10 as interval, t.*
            from t
           ) t
      group by interval

在这些查询中,“10”代表任意分钟数。请注意,这些是从午夜开始计算的,因此像17这样的值始终从当天的前17分钟开始。

interval的定义是日期的算术表达式。

trunc(orderdate)+ floor(((orderdate - trunc(orderdate))* 24 * 60)/ 10)* 10作为间隔,

第一部分trunc(orderdate)是Oracle语法,用于删除日期的时间部分。这会将日期移动到当天开始的午夜。

表达式orderdate - trunc(orderdate)计算自午夜以来的天数 - 这是一天的小数部分。因此,0.25将是早上6点。*24*60将此转换为分钟。因此,0.25变为0.25 * 60 * 24 = 360 - 从午夜起的分钟数。

然后表达式floor(x/y)*y简单地“截断”任何值到y的下半部分。因此,floor(118/10)为11,而11 * 10为110.换句话说,这会将* y和(a + 1)* y(最多不包括)之间的所有值映射到相同的值,a * Y

在2013-01-01上午6:08考虑实践中的表达:

`trunc(orderdate)` moves the date to midnight on 2013-01-01.
`orderdate - trunc(orderdate)` creates a number like 0.25.
`((orderdate - trunc(orderdate))*24*60)` produces the value 368
`floor(((orderdate - trunc(orderdate))*24*60)/10)*10` produces 360
`floor(((orderdate - trunc(orderdate))*24*60)/10)*10*(1/24*60)` produces 0.25

当这个被添加到明天时,时间再次变为早上6点。

答案 1 :(得分:3)

如果您需要更简单的方法来获取时间间隔 - 我无法帮助您,因为我不知道您的表格和数据:

-- Time interval - every 15 min from midnight --
SELECT To_Char(trunc(SYSDATE) + (LEVEL/1440*15), 'HH24:MI') interval_15_min 
  FROM dual
CONNECT BY LEVEL <= 10 -- this is orbitraty 
/
SQL>

INTERVAL_15_MIN
--------------
00:15
00:30
00:45
...