Суммируйте данные, которые уже были сгруппированы - PullRequest
3 голосов
/ 24 декабря 2011

У меня есть набор данных, который выглядит следующим образом:

  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

Другими словами, у меня есть группа столбцов в Задача и группа строк в Пользователь . Проблема в том, что я хочу, чтобы группа строк суммировалась в дополнительное время.

На первый взгляд, я мог бы просто вернуть имя пользователя обратно как «Все», и это суммировало бы, но это не дает мне средних значений, которые мне нужны. Мне нужно сначала СУММИТЬ время пользователя, а затем найти среднее значение для пользователя. Если я изменю способ формирования исходных данных, мои группы задач больше не будут работать должным образом.

Если я пытаюсь использовать строку «Итоги» в моей группе строк, она объединяет ОРИГИНАЛЬНЫЕ данные, а не суммированные / сгруппированные данные. Это довольно разочаровывает, потому что это на самом деле неправильно в моих глазах.

Ответы [ 4 ]

1 голос
/ 30 декабря 2011

Единственный способ, которым я смог реализовать этот тип функций, - это использовать раздел «Код» отчета. Я бы отслеживал групповые данные, которые хотел объединить в глобальную переменную, чтобы потом выводить в нужное поле.

Вот статья Microsoft, которая описывает, как встраивать код в ваш отчет. http://msdn.microsoft.com/en-us/library/ms159238.aspx

Вот гораздо более подробный способ решения вашей проблемы. Ссылка

0 голосов
/ 03 января 2012

Вот запрос, который я бы написал, который работает ... "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

Если ваши данные могут обеспечить, что у данного пользователя есть несколько записей для одной Задачи, например, 3 записи для Пользователя A, Задача X имеет времена 95, 100 и 105, у вас есть 3 записи для 300, что приводит к 100. Это может исказить ваше общее среднее значение этой задачи и придется изменить запрос.Дайте мне знать, если у человека будет несколько записей для данной задачи на основе производственных данных ... Если это так, то, вероятно, потребуется поместить элемент THAT в свой собственный предварительный запрос, где находится таблица "From AllUserTasks".

0 голосов
/ 31 декабря 2011

Предполагая, что ваш источник - 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

В этом блоге есть пример, который также может быть полезен

http://beyondrelational.com/blogs/jason/archive/2010/07/03/aggregate-of-an-aggregate-function-in-ssrs.aspx

Удачи

0 голосов
/ 30 декабря 2011

Я бы сделал это в сценарии 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.Мой пример просто объяснительный.

...