2013-07-29 10 views
1

enter image description here 이 작업은 Excel에서 쉽게 수행해야하지만이 계산은 SQL을 통해 수행해야합니다. GROUP BY, OVER()을 사용하여 SUM과 1 년의 %를 계산할 수 있습니다. 그러나 나는 3 년 동안 데이터를 한 번에 발표하지 않았다. 어떤 도움을 주시면 감사하겠습니다. 간단하게하기 위해서SQL Server에서 SUMIFS (여러 조건이있는 경우 합계)

+0

그래픽이 표시되지만 그룹화 방법에 대한 자세한 정보가 제공됩니까? 또한 원래 데이터 집합의 모습은 어떻습니까? –

+0

2010 년, 11, 12 년의 3 년 동안 3 년간의 타이프 A, B, C의 합계와 해당 연도의 백분율 (전체에 대한)을 갖기를 원합니다. – user2103670

+0

예, 복잡한 일을하고 싶지 않습니다. 3 년이면 충분합니다. 데이터가 커지면서 테이블이 커지도록 동적 피벗 (dynamic pivot) 또는 무언가를 할 수 있다고 생각합니다. – user2103670

답변

4

SQL Server를 사용하고 있으므로 SQL Server 2005 이상을 사용하는 경우 PIVOT 함수를 사용하여 결과를 얻을 수 있습니다. 이 솔루션은 결과를 얻기 위해 피벗 해제 프로세스와 피벗 프로세스를 모두 구현합니다. 이 결과에 대한 출발점은 유형별로 총 %와 총을 계산하는 것입니다

select type, year, total, 
    round(total/sum(total) over(partition by year)*100.0, 1) t_per, 
    sum(total) over(partition by type) t_type, 
    round(sum(total) over(partition by type)*100.0/sum(total) over(), 1) tot_per  
from tablea 

SQL Fiddle with Demo를 참조하십시오.

select type, 
    col = cast(year as varchar(4))+'_'+col, 
    value, 
    t_type 
from 
(
    select type, year, total, 
    round(total/sum(total) over(partition by year)*100.0, 1) t_per, 
    sum(total) over(partition by type) t_type, 
    round(sum(total) over(partition by type)*100.0/sum(total) over(), 1) tot_per 
    from tablea 
) d 
cross apply 
(
    select 'total', total union all 
    select 't_per', t_per 
) c (col, value); 

Demo를 참조하십시오 : 이것은 당신이 그래서 당신은 CROSS APPLY를 사용하여 여러 행에 데이터를 피벗 해제 할 수 있습니다 피벗 할 여러 열이있는 결과를 제공 할 것입니다. 마지막으로 당신은 col의 값에 PIVOT 기능을 적용 할 수

select type, 
    [2010_total], [2010_t_per], 
    [2011_total], [2011_t_per], 
    [2012_total], [2012_t_per], 
    t_type, 
    tot_per 
from 
(
    select type, 
    col = cast(year as varchar(4))+'_'+col, 
    value, 
    t_type, 
    tot_per 
    from 
    (
    select type, year, total, 
     round(total/sum(total) over(partition by year)*100.0, 1) t_per, 
     sum(total) over(partition by type) t_type, 
     round(sum(total) over(partition by type)*100.0/sum(total) over(), 1) tot_per  
    from tablea 
) d 
    cross apply 
    (
    select 'total', total union all 
    select 't_per', t_per 
) c (col, value) 
) s 
pivot 
(
    max(value) 
    for col in ([2010_total], [2010_t_per], 
       [2011_total], [2011_t_per], 
       [2012_total], [2012_t_per]) 
) piv 

SQL Fiddle with Demo를 참조하십시오. 하위 쿼리 대신 CTE를 사용하도록 리팩토링 될 수 있으며 연도를 알 수 없으면 동적 SQL을 사용하도록 변환 할 수도 있습니다. 당신이 값을 알 수없는 번호가있는 경우

, 다음 동적 SQL 코드는 다음과 같습니다

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(cast(year as varchar(4))+'_'+col) 
        from tablea 
        cross apply 
        (
         select 'total', 1 union all 
         select 't_per', 2 
        ) c (col, so) 
        group by year, col, so 
        order by year, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT type,' + @cols + ', t_type, tot_per 
      from 
      (
       select type, 
       col = cast(year as varchar(4))+''_''+col, 
       value, 
       t_type, 
       tot_per 
       from 
       (
       select type, year, total, 
        round(total/sum(total) over(partition by year)*100.0, 1) t_per, 
        sum(total) over(partition by type) t_type, 
        round(sum(total) over(partition by type)*100.0/sum(total) over(), 1) tot_per  
       from tablea 
      ) d 
       cross apply 
       (
       select ''total'', total union all 
       select ''t_per'', t_per 
      ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

Demo를 참조하십시오. 정적 버전과 동적 버전 모두 결과가 다음과 같이 표시됩니다.

| TYPE | 2010_TOTAL | 2010_T_PER | 2011_TOTAL | 2011_T_PER | 2012_TOTAL | 2012_T_PER | T_TYPE | TOT_PER | 
--------------------------------------------------------------------------------------------------------- 
| A |   1 |  16.7 |   1 |  16.7 |   1 |  16.7 |  3 | 16.7 | 
| B |   2 |  33.3 |   2 |  33.3 |   2 |  33.3 |  6 | 33.3 | 
| C |   3 |   50 |   3 |   50 |   3 |   50 |  9 |  50 | 
1

나는 수직으로이 결과를 표시하는 것을 선호 :

SELECT 
Type, 
Year, 
SUM(Total) as Dollars, 
ROUND(SUM(Total) * 100/(SELECT SUM(TOTAL) FROM TableA t2 WHERE t2.Year = t1.Year),1) as Per 
FROM TableA t1 
Group By Type, Year 

출력 :

TYPE YEAR DOLLARS PERCENT 

    A 2010 1 16.7 
    B 2010 2 33.3 
    C 2010 3 50 
    A 2011 1 16.7 
    B 2011 2 33.3 
    C 2011 3 50 
    A 2012 1 16.7 
    B 2012 2 33.3 
    C 2012 3 50 

Sql Fiddle Demo

+0

감사하지만 테이블을 수평으로 움직이는 트릭을하지는 않습니다. – user2103670

+0

@ user2103670 정확히 무엇을 원하십니까? 이것은 모든 레코드의 유형, 연도 및 합계를 반환합니다. ;) –

+0

@FabianBigler OP가 제공하는 결과 테이블에는 9 개의 열이 있지만 3 개의 열만 있습니다. – Parado

4

SUMIFSUM(case statement)와 SQL에 복제 할 수 있습니다 :

SELECT Type 
     ,SUM(CASE WHEN Year = '2010' THEN Total ELSE 0 END)'2010 Total' 
     ,SUM(CASE WHEN Year = '2010' THEN Total ELSE 0 END)*1.0/SUM(SUM(CASE WHEN Year = '2010' THEN Total ELSE 0 END)) OVER() '2010 Percent of Total' 
     ,SUM(CASE WHEN Year = '2011' THEN Total ELSE 0 END)'2011 Total' 
     ,SUM(CASE WHEN Year = '2011' THEN Total ELSE 0 END)*1.0/SUM(SUM(CASE WHEN Year = '2011' THEN Total ELSE 0 END)) OVER() '2011 Percent of Total' 
     ,SUM(CASE WHEN Year = '2012' THEN Total ELSE 0 END)'2012 Total' 
     ,SUM(CASE WHEN Year = '2012' THEN Total ELSE 0 END)*1.0/SUM(SUM(CASE WHEN Year = '2012' THEN Total ELSE 0 END)) OVER() '2012 Percent of Total' 
     ,SUM(Total) 'Total' 
     ,SUM(Total)*1.0/SUM(SUM(Total)) OVER() 'Percent of Total' 

FROM Table 
GROUP BY Type