我有以下信息(按视图返回):
DateTime ItemID UserTyp Seconds
2012-01-01 10 S 12
2012-01-01 10 S 18
2012-01-01 11 S 22
2012-01-02 11 M 52
2012-01-02 10 S 120
2012-01-02 11 S NULL
2012-01-03 15 M 112
2012-01-03 12 S 182
2012-01-04 10 M NULL
我需要做的是按用户类型计算所有秒数的总和,但是有五个时间段。
期间按以下方式设定:
然后对于每个时段,根据DateTime和记录的UserType,我应该拿出这些记录:
Periods UserTypeS_SUM(Seconds) UserTypeM_SUM(Seconds)
1
2
3
4
5
此外,我应该检查是否有至少5条记录,在分割之前 - 如果我有4例,那么只会使用一个句号。
我知道它看起来并没有那么不同,我已经开始使用函数制作解决方案,但它对我来说看起来有点无效。是否有一些内置函数可以轻松实现这一目标?
编辑:我真的很抱歉,但我忘了提到我应该在视图或表值函数中。在这种情况下,不允许存储过程。答案 0 :(得分:2)
试试这个:
;with cte as(
select *,NTILE(5) over(order by [DateTime]) as period
from Table1
),
type_S as( select period,SUM([Seconds]) as UserTypeS_SUM
from cte
where [UserTyp]='S'
group by period),
type_M as( select period,SUM([Seconds]) as UserTypeM_SUM
from cte
where [UserTyp]='M'
group by period),
seq as (
select 1 as sno union all
select 2 union all
select 3 union all
select 4 union all
select 5 )
select seq.sno as period,UserTypeS_SUM, UserTypeM_SUM
from seq
left join type_s s
on seq.sno=s.period
left join type_m m
on seq.sno=m.period
答案 1 :(得分:1)
这里是查询:
创建数据:
create table #t (d DateTime, ItemID int, UserTyp char(1), Seconds int);
insert into #t
values
('2012-01-01', 10, 'S', 12 ),
('2012-01-01', 10, 'S', 18 ),
('2012-01-01', 11, 'S', 22 ),
('2012-01-02', 11, 'M', 52 ),
('2012-01-02', 10, 'S', 120 ),
('2012-01-02', 11, 'S', NULL ),
('2012-01-03', 15, 'M', 112 ),
('2012-01-03', 12, 'S', 182 ),
('2012-01-04', 10, 'M', NULL );
--to other users: be free to take it for your own reply
查询:已编辑的@Manatherin评论
;with
one_to_five as (
select 1 as n union all
select 2 as n union all
select 3 as n union all
select 4 as n union all
select 5 as n
),
max_min as (
select UserTyp, max(d) as max_d, min(d) as min_d
from #t
group by UserTyp),
time_for_period as (
select UserTyp, datediff( second, min_d, max_d ) / 5.0 as elapsed_time
from max_min),
periods as (
select o2f.n, t4p.UserTyp,
dateadd(second ,elapsed_time * (n - 1) ,mm.min_d ) as beginPeriod,
dateadd(second ,elapsed_time * (n ) ,mm.min_d ) as endPeriod
from time_for_period t4p
inner join max_min mm on t4p.UserTyp = mm.UserTyp
cross join one_to_five o2f
)
select n, p.UserTyp, coalesce(sum( seconds ),0)
from periods p
left outer join #t t
on t.UserTyp = p.UserTyp and
t.d between p.beginPeriod and p.endPeriod
group by n, p.UserTyp
order by 2,1;
n UserTyp
- ------- ---
1 M 52
2 M 0
3 M 112
4 M 0
5 M 0
1 S 52
2 S 0
3 S 120
4 S 0
5 S 182
此时你应该按用户进行转动。
免责声明:我已经编写了查询,但我没有回去查看结果的一致性,可以自由调试。