2

我有以下信息(按视图返回):

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  

我需要做的是按用户类型计算所有秒数的总和,但要计算五个周期。

期间按以下方式设置:

  1. 获取第一个和最后一个日期
  2. 五天一分为二
  3. 除法的结果是一个周期包含的天数

然后对于每个时期,根据记录的 DateTime 和 UserType,我应该得出以下记录:

Periods  UserTypeS_SUM(Seconds) UserTypeM_SUM(Seconds)
1        
2        
3
4
5

另外,我应该在进行除法之前检查是否至少有 5 条记录——例如,如果我有 4 条,则只使用一个句点。

我知道它看起来并没有那么不同,我已经开始使用函数制作解决方案,但它看起来对我来说有点无效。是否有一些内置函数可以轻松做到这一点?

编辑:我真的很抱歉,但我忘记提到我应该在视图或表值函数中使用这个。在这种情况下不允许存储过程。

4

2 回答 2

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


SQL小提琴演示

于 2012-10-19T08:41:22.713 回答
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

此时您应该按用户进行旋转。

免责声明:我已经编写了查询,我不会回去查看结果的一致性,可以自由调试它。

于 2012-10-19T08:16:57.260 回答