我希望以30分钟的时间间隔记录用户数。
总共有48个间隔。如果用户登录数据库然后他/她的start_time(登录)和end_time(退出时间),userid将被记录到表中 用户可以登录多个时间段。我正在考虑2017-jul-12数据 对于ex: ID为2的用户登录2次,因此该用户的计数值为2(12:02到12:07和11:46 pm到11:51 pm)类似地,如果用户登录到一个时间段并且登出到计数之外的其他时间段将被处理两个间隔,即2 例如:id为3的用户......
输入
user start_date end_time
1 12-JUL-17 12.02.09.430000000 AM 12-JUL-17 12.02.13.310000000 AM
2 12-JUL-17 12.02.13.323000000 AM 12-JUL-17 12.07.33.343000000 AM
3 12-JUL-17 12.06.19.203000000 AM 12-JUL-17 12.37.49.890000000 AM
4 12-JUL-17 12.07.33.357000000 AM 12-JUL-17 12.07.37.813000000 AM
5 12-JUL-17 12.07.37.813000000 AM 12-JUL-17 12.07.40.690000000 AM
6 12-JUL-17 12.07.40.707000000 AM 12-JUL-17 12.12.58.470000000 AM
7 12-JUL-17 12.12.58.487000000 AM 12-JUL-17 12.13.01.937000000 AM
8 12-JUL-17 12.13.01.950000000 AM 12-JUL-17 12.18.22.193000000 AM
9 12-JUL-17 12.13.20.267000000 AM 12-JUL-17 12.45.38.013000000 AM
2 12-JUL-17 11.46.17.827000000 PM 12-JUL-17 11.51.32.267000000 PM
3 12-JUL-17 11.47.03.497000000 PM 13-JUL-17 12.20.17.167000000 AM
输出
count(id) interval
9 1
2 2
0 47
2 48
共有48个间隔(每个30分钟)
count(id) interval
9 1 (12 - 12:30 am)
2 2 (12:30 - 1:00 am)
. .
. .
. 47 (11:00 - 11:30 pm)
2 48 (11:30 - 12:00 am)
查询
With Periods as
(
select to_timestamp(:TheDate, 'yyyy-mm-dd hh24:mi:ss') + (level-1)/48 as p_start, to_timestamp(:TheDate, 'yyyy-mm-dd hh24:mi:ss') + (level)/48 as p_end, level as p_id
from dual connect by level<=48
)
select p.*, count(distinct t1.id) as distinct_users
from Periods p
left join Input t1
on t1.start_date < p_end
and t1.end_date >= p_start
group by p.p_id, p.p_start, p.p_end
我已经玩过这个查询,但它没有给我一个准确的答案 注意:两个日期列都在时间戳
答案 0 :(得分:1)
我想通过连接ALL_OBJECTS WHERE rownum&lt; = 48来表示不同的间隔。然后,您将其与期间表连接,并按用户对其进行分组。
SELECT intervals.interval, COUNT(DISTINCT "USER") FROM (SELECT rownum AS interval FROM all_objects WHERE rownum <= 48) intervals
LEFT OUTER JOIN test2 ON intervals.interval BETWEEN EXTRACT(HOUR FROM start_date) * 2 + FLOOR(EXTRACT(MINUTE FROM start_date)/30) + 1
AND CASE WHEN EXTRACT(DAY FROM start_date) != EXTRACT(DAY FROM end_time) THEN 48 ELSE EXTRACT(HOUR FROM end_time) * 2 + FLOOR(EXTRACT(MINUTE FROM end_time)/30) + 1 END
GROUP BY intervals.interval
ORDER BY intervals.interval