统计一个时间跨度内每小时的记录数
Count records per hour within a time span
我有一个 table,其中包含用户 ID、开始日期和结束日期。
我想按小时统计关注的userID数量
例如startDate = '21/05/2014 01:15:00' 且endDate = '21/05/2014 05:22:00' 的用户 '4242' 应该从01开始算一次到 02,一次从 02 到 03,一次从 03 到 04,...
它会给出这样的结果:
DATE AND TIME COUNT
-------------------------------------
20140930 18-19 198
20140930 19-20 220
20140930 20-21 236
20140930 21-22 257
20140930 22-23 257
20140930 23-00 257
20141001 00-01 259
20141001 01-02 259
20141001 02-03 258
20141001 03-04 259
20141001 04-05 258
20141001 05-06 258
你会怎么做?
好吧,我尝试了很多东西。这是我最近的尝试。如果代码太乱,请不要阅读它,请告诉我您将如何处理这个问题;)谢谢!
WITH timespan AS (
SELECT lpad(rownum - 1,2,'00') ||'-'|| lpad(mod(rownum,24),2,'00') AS hours
FROM dual
connect BY level <= 24
),
UserID_min_max AS (
SELECT USERS.UserID,
min(USERS.date_startUT) AS min_date,
max(USERS.date_end) AS max_date,
code_etat
FROM USERS
WHERE (
(USERS.date_startUT >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR ( USERS.date_startUT <= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR (USERS.date_startUT BETWEEN to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss') AND to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss')))
GROUP BY USERS.UserID, code_etat
),
hours_list AS (
SELECT UserID, min_date, max_date, code_etat
, to_char(min_date + row_number() over (partition BY UserID ORDER BY 1)-1,'yyyymmdd') AS days
, to_char(min_date,'yyyymmdd') AS date_start
, to_char(min_date, 'hh24') || '-' || lpad(to_number(to_char(min_date, 'hh24')) + 1, 2, '00') AS timespan_date_start
, to_char(max_date,'yyyymmdd') AS date_end
, to_char(max_date, 'hh24') || '-' || lpad(to_number(to_char(max_date, 'hh24')) + 1, 2, '00') AS timespan_date_end
FROM UserID_min_max cmm
connect BY level <= trunc(max_date) - trunc(min_date)+1
AND PRIOR UserID = UserID
AND prior sys_guid() IS NOT NULL
),
all_timespan_hours_list AS (
SELECT lj.*, t.*, lj.days ||' '|| t.hours AS days_hours
FROM hours_list lj
JOIN timespan t
ON lj.days || t.hours >= lj.date_start || lj.timespan_date_start
AND lj.days || t.hours <= lj.date_end || lj.timespan_date_end
)
SELECT DISTINCT days_hours, COUNT(*)
FROM (
SELECT *
FROM all_timespan_hours_list ttlj
WHERE CODE_ETAT IN ('SOH','SOL')
)
GROUP BY days_hours
ORDER BY days_hours;
试试这个:
SELECT
DATE_FORMAT(your_datetime_column, '%Y%m%d %H') AS `hourly`,
COUNT(*) AS `count`
FROM your_table
GROUP BY DATE_FORMAT(your_datetime_column, '%Y%m%d %H')
下面是我将如何做类似的事情:
with dt_tab as (select trunc(:p_start_date, 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(:p_end_date, 'hh') - trunc(:p_start_date, 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, :p_end_date) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
:p_start_date := 20/05/2015 08:00:00
:p_end_date := 21/05/2015 08:00:00
DATE_AND_TIME CNT
---------------- ---
20/05/2015 08-09 0
20/05/2015 09-10 0
20/05/2015 10-11 0
20/05/2015 11-12 0
20/05/2015 12-13 0
20/05/2015 13-14 0
20/05/2015 14-15 0
20/05/2015 15-16 0
20/05/2015 16-17 0
20/05/2015 17-18 0
20/05/2015 18-19 0
20/05/2015 19-20 1
20/05/2015 20-21 1
20/05/2015 21-22 1
20/05/2015 22-23 1
20/05/2015 23-00 1
21/05/2015 00-01 1
21/05/2015 01-02 1
21/05/2015 02-03 1
21/05/2015 03-04 1
21/05/2015 04-05 1
21/05/2015 05-06 1
21/05/2015 06-07 0
21/05/2015 07-08 1
21/05/2015 08-09 0
(根据您的时间段开始日期和结束日期的配置方式,您可能希望更改使用绑定变量 - 例如,在 table 中使用 min/max 日期等)
当我在 Toad 中 运行 以上内容有效。对于在 SQL*Plus 中工作的东西,或者当你 运行 它作为脚本(例如在 Toad 中)时,下面应该工作:
variable p_start_date varchar2(20)
variable p_end_date varchar2(20)
exec :p_start_date := '20/05/2015 08:00:00';
exec :p_end_date := '21/05/2015 08:00:00';
with dt_tab as (select trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') - trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss')) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
尝试像这样使用函数 TRUNC(date,[fmt]):
select trunc(some_date, 'HH24')
from some_table
group by trunc(some_date, 'HH24');
我有一个 table,其中包含用户 ID、开始日期和结束日期。 我想按小时统计关注的userID数量
例如startDate = '21/05/2014 01:15:00' 且endDate = '21/05/2014 05:22:00' 的用户 '4242' 应该从01开始算一次到 02,一次从 02 到 03,一次从 03 到 04,...
它会给出这样的结果:
DATE AND TIME COUNT
-------------------------------------
20140930 18-19 198
20140930 19-20 220
20140930 20-21 236
20140930 21-22 257
20140930 22-23 257
20140930 23-00 257
20141001 00-01 259
20141001 01-02 259
20141001 02-03 258
20141001 03-04 259
20141001 04-05 258
20141001 05-06 258
你会怎么做?
好吧,我尝试了很多东西。这是我最近的尝试。如果代码太乱,请不要阅读它,请告诉我您将如何处理这个问题;)谢谢!
WITH timespan AS (
SELECT lpad(rownum - 1,2,'00') ||'-'|| lpad(mod(rownum,24),2,'00') AS hours
FROM dual
connect BY level <= 24
),
UserID_min_max AS (
SELECT USERS.UserID,
min(USERS.date_startUT) AS min_date,
max(USERS.date_end) AS max_date,
code_etat
FROM USERS
WHERE (
(USERS.date_startUT >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR ( USERS.date_startUT <= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR (USERS.date_startUT BETWEEN to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss') AND to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss')))
GROUP BY USERS.UserID, code_etat
),
hours_list AS (
SELECT UserID, min_date, max_date, code_etat
, to_char(min_date + row_number() over (partition BY UserID ORDER BY 1)-1,'yyyymmdd') AS days
, to_char(min_date,'yyyymmdd') AS date_start
, to_char(min_date, 'hh24') || '-' || lpad(to_number(to_char(min_date, 'hh24')) + 1, 2, '00') AS timespan_date_start
, to_char(max_date,'yyyymmdd') AS date_end
, to_char(max_date, 'hh24') || '-' || lpad(to_number(to_char(max_date, 'hh24')) + 1, 2, '00') AS timespan_date_end
FROM UserID_min_max cmm
connect BY level <= trunc(max_date) - trunc(min_date)+1
AND PRIOR UserID = UserID
AND prior sys_guid() IS NOT NULL
),
all_timespan_hours_list AS (
SELECT lj.*, t.*, lj.days ||' '|| t.hours AS days_hours
FROM hours_list lj
JOIN timespan t
ON lj.days || t.hours >= lj.date_start || lj.timespan_date_start
AND lj.days || t.hours <= lj.date_end || lj.timespan_date_end
)
SELECT DISTINCT days_hours, COUNT(*)
FROM (
SELECT *
FROM all_timespan_hours_list ttlj
WHERE CODE_ETAT IN ('SOH','SOL')
)
GROUP BY days_hours
ORDER BY days_hours;
试试这个:
SELECT
DATE_FORMAT(your_datetime_column, '%Y%m%d %H') AS `hourly`,
COUNT(*) AS `count`
FROM your_table
GROUP BY DATE_FORMAT(your_datetime_column, '%Y%m%d %H')
下面是我将如何做类似的事情:
with dt_tab as (select trunc(:p_start_date, 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(:p_end_date, 'hh') - trunc(:p_start_date, 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, :p_end_date) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
:p_start_date := 20/05/2015 08:00:00
:p_end_date := 21/05/2015 08:00:00
DATE_AND_TIME CNT
---------------- ---
20/05/2015 08-09 0
20/05/2015 09-10 0
20/05/2015 10-11 0
20/05/2015 11-12 0
20/05/2015 12-13 0
20/05/2015 13-14 0
20/05/2015 14-15 0
20/05/2015 15-16 0
20/05/2015 16-17 0
20/05/2015 17-18 0
20/05/2015 18-19 0
20/05/2015 19-20 1
20/05/2015 20-21 1
20/05/2015 21-22 1
20/05/2015 22-23 1
20/05/2015 23-00 1
21/05/2015 00-01 1
21/05/2015 01-02 1
21/05/2015 02-03 1
21/05/2015 03-04 1
21/05/2015 04-05 1
21/05/2015 05-06 1
21/05/2015 06-07 0
21/05/2015 07-08 1
21/05/2015 08-09 0
(根据您的时间段开始日期和结束日期的配置方式,您可能希望更改使用绑定变量 - 例如,在 table 中使用 min/max 日期等)
当我在 Toad 中 运行 以上内容有效。对于在 SQL*Plus 中工作的东西,或者当你 运行 它作为脚本(例如在 Toad 中)时,下面应该工作:
variable p_start_date varchar2(20)
variable p_end_date varchar2(20)
exec :p_start_date := '20/05/2015 08:00:00';
exec :p_end_date := '21/05/2015 08:00:00';
with dt_tab as (select trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') - trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss')) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
尝试像这样使用函数 TRUNC(date,[fmt]):
select trunc(some_date, 'HH24')
from some_table
group by trunc(some_date, 'HH24');