I want to group the data in a table by time interval. The table keeps the order info that includes the userid, item name, model, quantity, activity date, etc. Now I want to group this data by time intervals. The time interval could be anything like 5 min, 10 min, 15, etc. Also, the query should return only those users (all the column data) who made orders more than once within that 5 minutes interval. Is it possible to achieve this in one SQL query? I use Oracle.
Thank you
Edit:
Sample data
**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
I expect to get:
**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
Yes. Presumably you want to see the result as a datetime value as well. This requires some datetime arithmetic. Basically, getting the number of minutes since midnight, dividing by the number of minutes and then multiplying again (to round down). Then adding back in the time at midnight:
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
To group by time intervals, you would use:
select interval, count(*)
from (select trunc(orderdate)+floor(((orderdate - trunc(orderdate))*24*60)/10)*10 as interval, t.*
from t
) t
group by interval
In these queries, "10" stands for any number of minutes. Note that these are calculated since midnight, so a value like 17 always starts with the first 17 minutes of the day.
The definition of interval is an arithmetic expression on dates.
trunc(orderdate)+floor(((orderdate - trunc(orderdate))*24*60)/10)*10 as interval,
The first part, trunc(orderdate)
, is Oracle syntax for removing the time part of a date. This moves the date to midnight at the beginning of the day.
The expression orderdate - trunc(orderdate)
calculates the number of days since midnight -- this is a fractional part of one day. So, 0.25 would be 6:00 a.m. The *24*60
converts this to minutes. So, 0.25 becomes 0.25*60*24 = 360 -- the number of minutes since midnight.
Then the expression floor(x/y)*y
simply "truncates" any value to the lower multiple of y. So, floor(118/10)
is 11, and 11*10 is 110. In other words, this will map all values between a*y and (a+1)*y (up to not including) to the same value, a*y.
Consider the expression in practice, on 6:08 a.m. on 2013-01-01:
`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
And when this is added to minight, the time turns into 6:00 a.m. again.
In case you need simpler way to get time interval - I cannot help you with anything else as i do not know your tables and data:
-- 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
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With