2011-12-23 167 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」表中。