我在mssql 2008数据库中有一些电话呼叫数据,并希望将其拆分为15(或X)分钟间隔,以便在某些Erlang计算中使用。
调用logg:
call start end
1 2011-01-01 12:00:01 2011-01-01 12:16:00
2 2011-01-01 12:14:00 2011-01-01 12:17:30
3 2011-01-01 12:29:30 2011-01-01 12:46:20
将显示为
call start end
1 2011-01-01 12:00:01 2011-01-01 12:15:00
1 2011-01-01 12:15:00 2011-01-01 12:16:00
2 2011-01-01 12:14:00 2011-01-01 12:15:00
2 2011-01-01 12:15:00 2011-01-01 12:17:30
3 2011-01-01 12:29:30 2011-01-01 12:30:00
3 2011-01-01 12:30:00 2011-01-01 12:45:00
3 2011-01-01 12:45:00 2011-01-01 12:46:20
有没有人对如何做到这一点有什么好的建议?
提前致谢
答案 0 :(得分:3)
Richard是对的,这个查询将调用分成15分钟的时间间隔:
试试这个:
With CallData ([call],start,[end]) as
(
select [call],start,case when [end]<=dateadd(minute,15,start) then [end] else dateadd(minute,15,start) end as [end] from CallLogTable
union all
select CallData.[call],CallData.[end],case when CallLogTable.[end]<=dateadd(minute,15,CallData.[end]) then CallLogTable.[end] else dateadd(minute,15,CallData.[end]) end as [end] from CallLogTable join CallData on CallLogTable.[call]=CallData.[call]
where CallData.[end]<case when CallLogTable.[end]<=dateadd(minute,15,CallData.[end]) then CallLogTable.[end] else dateadd(m,15,CallData.[end]) end
)
select * from CallData
不幸的是,我手头没有SQL,所以我无法测试它。然而,这是一个想法,所以你可能会设法调整它,以防它在某个地方失败。
我把别名和错误用m而不是分钟。你能试试看它是否有效。 TX。 (未完成测试时会发生这种情况)
要在15分钟(00/15/30/45)拆分它,你可以使用:
With CallData ([call],start,[end]) as
(
select [call],start,case when [end]<=dateadd(minute,15*((datediff(minute,0,start)/15)+1),0) then [end] else dateadd(minute,15*((datediff(minute,0,start)/15)+1),0) end as [end] from CallLogTable
union all
select CallData.[call],CallData.[end],case when CallLogTable.[end]<=dateadd(minute,15*((datediff(minute,0,CallData.[End])/15)+1),0) then CallLogTable.[end] else dateadd(minute,15*((datediff(minute,0,CallData.[End])/15)+1),0) end as [end] from CallLogTable join CallData on CallLogTable.[call]=CallData.[call]
where CallData.[end]<case when CallLogTable.[end]<=dateadd(minute,15*((datediff(minute,0,CallData.[End])/15)+1),0) then CallLogTable.[end] else dateadd(minute,15*((datediff(minute,0,CallData.[End])/15)+1),0) end
)
select * from CallData order by [call],start
答案 1 :(得分:3)
样本表
create table CallLogTable (call int, start datetime, [end] datetime)
insert CallLogTable select
1, '2011-01-01 12:00:01', '2011-01-01 12:16:00' union all select
2, '2011-01-01 12:14:00', '2011-01-01 12:17:30' union all select
3, '2011-01-01 12:29:30', '2011-01-01 12:46:20'
查询
select
call,
case when st < start then start else st end [start],
case when et > [end] then [end] else et end [end]
from (select *,
xstart = dateadd(mi, 15*(datediff(mi, 0, d.start)/15), 0),
blocks = datediff(mi, d.[start], d.[end])/15+2
from CallLogTable d) d
cross apply (
select
st = dateadd(mi,v.number*15,xstart),
et = dateadd(mi,v.number*15+15,xstart)
from master..spt_values v
where v.type='P' and v.number <= d.blocks
and d.[end] > dateadd(mi,v.number*15,xstart)) v
order by call, start
如果要创建此查询的视图,请删除最后一个[order by]行
注释
dateadd(mi, 15*(datediff(mi, 0, d.start)/15), 0)
计算呼叫开始的15分钟边框答案 2 :(得分:0)
一天只有1440分钟。因此,您可以创建并填充1440行MINUTES表,其主键是一个四位数字,表示24小时格式的小时分钟(例如,下午9:13将是2113)。然后,您可以在该表中包含尽可能多的列,以表示当天的任何一分钟:它所属的四分之一小时,是否被视为非高峰或高峰,其计费率在计划A下是什么,等等上。您只需根据用例需要添加列。完全可扩展。
在您的示例中,第一列MINUTES.QuarterHour将指示分钟落入哪个季度小时。例如,02:17是在季度小时6。填充表后,您只需使用HHMMChunk = MINUTES上的简单连接,即可使用电话呼叫表中日期时间值的HHMM块来回退该时间所属的四分之一小时。 ID。优点:查询更简单,更易于编写和维护,并且可能没有计算密集型。
编辑:该方法也是通用的和可移植的(即不是特定于实现的)。
答案 3 :(得分:0)
引人入胜的问题!
仅仅是为了踢,这是一个PostgreSQL方法,使用generate_sequence()来填充内部15分钟的间隔。毫无疑问,这是建立第一个和最后一个区间的前两个联盟的合并方式,但这仍然是读者的练习。
select
c.call
,c.dt_start - date_trunc('day', c.dt_start) as "begin"
,(date_trunc('second', (cast (c.dt_start - date_trunc('day', c.dt_start) as interval)
/ (15*60) + interval '1 second'))) * (15*60) as "end"
from
call c
where
(date_trunc('second', (cast (c.dt_start - date_trunc('day', c.dt_start) as interval)
/ (15*60) + interval '1 second'))) * (15*60)
<= date_trunc('second', (cast (c.dt_end - date_trunc('day', c.dt_end) as interval)
/ (15*60))) * (15*60)
union select
c.call
,greatest(
c.dt_start - date_trunc('day', c.dt_start),
date_trunc('second', (cast (c.dt_end - date_trunc('day', c.dt_end) as interval)
/ (15*60))) * (15*60)
) as "t_last_q"
,c.dt_end - date_trunc('day', c.dt_end) as "t_end"
from
call c
union select TQ.call, TQ.t_next_q, SEQ.SLICE
from
(select cast(g || ' seconds' as interval) as SLICE
from generate_series(0, 86400, 15*60) g) SEQ,
(select
c.call
,(date_trunc('second', (cast (c.dt_start - date_trunc('day', c.dt_start) as interval)
/ (15*60) + interval '1 second'))) * (15*60) as "t_next_q"
,date_trunc('second', (cast (c.dt_end - date_trunc('day', c.dt_end) as interval)
/ (15*60))) * (15*60) as "t_last_q"
from
call c
) TQ
where
SEQ.SLICE > TQ.t_next_q
and SEQ.SLICE <= TQ.t_last_q