我有一个如下所示的数据集:
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
换句话说,我在任务上有一个列组,在用户上有一个行组。问题是我希望行组总结一个额外的时间。
乍一看,我可以将用户的名字作为“全部”返回,它会进行总结,但实际上并没有给出我需要的平均值。我需要先按用户SUM时间,然后找到每个用户的平均值。如果我改变原始数据的形成方式,我的任务组将无法正常工作。
如果我尝试在我的行组中使用“总计”行,它会聚合ORIGINAL数据而不是汇总/分组数据。这是相当令人失望的,因为它在我眼中实际上是不正确的。
答案 0 :(得分:1)
我能够执行此类功能的唯一方法是使用报告的“代码”部分。我会跟踪我想要在全局变量中汇总的组数据,以后我将输出到我想要的字段。
这是一篇微软文章,介绍如何将代码嵌入到报表中 http://msdn.microsoft.com/en-us/library/ms159238.aspx
这是解决问题的更详细方法。 Link
答案 1 :(得分: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时,可以使用pivot而不是多个连接来优化脚本。 我的例子只是解释性的。
答案 2 :(得分:0)
假设您的源是SQL Server 2008,您可以使用分组集的组合:
http://technet.microsoft.com/en-us/library/bb522495.aspx
SSRS聚合函数:
http://msdn.microsoft.com/en-us/library/ms155830(v=sql.90).aspx
此博客有一个可能有用的示例
祝你好运
答案 3 :(得分: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这可能会扭曲你的OVERALL此任务的平均值,并且必须修改查询。让我知道一个人是否会根据生产数据为每个给定任务分配多个条目...如果是这样,那么可能需要将该元素放入其“FromUserTasks”表中的OWN预查询中。