2011-12-23 170 views
3

我有一个数据集,看起来像这样:汇总数据

User | Task | Time 
--------|--------|-------- 
User A | Task X | 100 
User A | Task Y | 200 
User A | Task Z | 300 
User B | Task X | 400 
User B | Task Y | 500 
User B | Task Z | 600 
User C | Task X | 700 
User C | Task Y | 800 
User C | Task Z | 900 
User D | Task X | 1000 
User D | Task Y | 1100 
user D | Task Z | 1200 

当我做我的初步分组,数据看起来是这样的:

 | Avg User | Avg Task X | Avg Task Y | Avg Task Z 
    User | Time | Time | Time | Time 
-------|----------|------------|------------|------------ 
User A | 200 | 100  | 200  | 300 
User B | 500 | 400  | 500  | 600 
User C | 800 | 700  | 800  | 900 
User D | 1100 | 1000  | 1100  | 1200 

我需要它看起来是这样的:

 | Avg User | Avg Task X | Avg Task Y | Avg Task Z 
User | Time | Time | Time | Time 
------|----------|------------|------------|------------ 
All | 650 | 550  | 650  | 750 

这是我如何得到这些数字:

650 = (200+500+800+1100)/4 
550 = (100+400+700+1000)/4 
650 = (200+500+800+1100)/4 
750 = (300+600+900+1200)/4 

换句话说,我有任务列组和用户行组。问题是我希望行组在额外的时间内汇总。

乍一看,我可以将用户的姓名作为“全部”返回,总结,但实际上并没有给我所需的平均值。我需要首先按用户总结时间,然后查找每个用户的平均值。如果我改变原始数据的形状,我的任务组将不再正常工作。

如果我尝试在我的行组上使用“总计”行,它将聚合原始数据而不是聚合/分组数据。这是相当令人失望的,因为它在我眼中实际上是不正确的。

回答

1

我能够做到这一类功能的唯一方法就是使用报告的代码部分。我会跟踪我想汇总在一个全局变量中的组数据,以便稍后输出到我想要的字段。

这里是一个微软的文章来描述如何嵌入代码到您的报告 http://msdn.microsoft.com/en-us/library/ms159238.aspx

这里是一个更详细的方式来解决问题。 Link

+0

我还不确定这是否能解决我的问题,但无论如何我正在学习一些东西。感谢您的反馈。 –

+0

我已经分组了列和行。看起来,这种方法不喜欢和分组列一起工作。 –

0

我会在一个sql脚本中这样做,在报告中这样做会过度(尽管它可能会是可能的)。

我已经和这里的示例脚本:

drop table #tmp, #tmp2, #tmp3 

select 'User A' as [User],' Task X ' as [Task],100.00 as [Time] 
into #tmp 
union all 
select 'User A ',' Task Y ',200 
union all 
select 'User A ',' Task Z ',300 
union all 
select 'User B ',' Task X ',400 
union all 
select 'User B ',' Task Y ',500 
union all 
select 'User B ',' Task Z ',600 
union all 
select 'User C ',' Task X ',700 
union all 
select 'User C ',' Task Y ',800 
union all 
select 'User C ',' Task Z ',900 
union all 
select 'User D ',' Task X ',1000 
union all 
select 'User D ',' Task Y ',1100 
union all 
select 'User D ',' Task Z ',1200 

select [User], 
    Task, 
    Sum(time) as time 
into #tmp2 
from #tmp 
group by [User], 
    [Task] 

select [User], 
    avg(time) as time 
into #tmp3 
from #tmp2 
group by [User]; 

declare @statement nvarchar(max); 
select @statement = 
'with cteTimes as (
    select * 
    from #tmp2 t 
     pivot (sum (t.[time]) for Task in (' + stuff((select ', ' + quotename([Task]) from #tmp group by [Task] for xml path, type).value('.','varchar(max)'), 1, 2, '') + ')) as Task 
) 
select ''All'' as [User], 
    (select avg(usr.time) from #tmp3 usr),' 
+ stuff((select ', avg(' + quotename([Task]) + ') as ' + quotename([Task]) from #tmp group by [Task] for xml path, type).value('.','varchar(max)'), 1, 2, '') + 
+'from cteTimes x '; 

exec sp_executesql @statement; 

脚本也许可以通过使用旋转,而不是多个,同时创造了#TMP4连接进行优化。 我的例子只是解释性的。

+0

我想我应该指出,任务类型是动态的。如果可以,我很乐意避免使用动态SQL –

+0

SQL必须是动态的,才能做到这一点。 我已将脚本更新为动态。 – AndrewBay

0

下面是我写的作品......的“PreQuery”做是为了组数和每个元素的总和给定用户的查询......然后就是卷起到“全部”的最高级别。现在,这是基于你的数据样本。

SELECT 
    AVG(TaskTime/TaskCount) as TaskAvg, 
    SUM(XTime)/SUM(XCount) as XAvg, 
    SUM(YTime)/SUM(YCount) as YAvg, 
    SUM(ZTime)/SUM(ZCount) as ZAvg 
    from 
     (SELECT 
       user, 
       COUNT(*) as TaskCount, 
       SUM(Time) as TaskTime, 
       CASE WHEN Task = "Task X" THEN 1 ELSE 0 END as XCount, 
       CASE WHEN Task = "Task X" THEN Time ELSE 0 END as XTime, 
       CASE WHEN Task = "Task Y" THEN 1 ELSE 0 END as YCount, 
       CASE WHEN Task = "Task Y" THEN Time ELSE 0 END as YTime, 
       CASE WHEN Task = "Task Z" THEN 1 ELSE 0 END as ZCount, 
       CASE WHEN Task = "Task Z" THEN Time ELSE 0 END as ZTime 
      FROM 
       AllUsersTasks 
      group by ; 
       user) PreQuery 

如果您的数据可以提供一个给定的用户有一个任务多个条目,用户A等3项,任务X具有95,100和105次,你有3个条目300结果为100.这可能会导致此任务的总体平均值偏差,并且必须修改查询。让我知道一个人是否会根据生产数据为每个给定任务创建多个条目...如果是这样,那么THAT元素可能需要放入它的OWN预查询中“From AllUserTasks”表中。