2013-07-29 49 views
1

enter image description here 這應該在Excel中很容易完成,但是,我想通過SQL來完成這種計算。我可以用GROUP BYOVER()計算一年的總和,並%。但是我沒有提供3年的數據。任何幫助將不勝感激。SUMIFS(總和如果與多個條件)與SQL Server

+0

我看到了您的圖形,但是您提供了有關如何分組的更多詳細信息?另外,你的原始數據集是什麼樣的? –

+0

我有2010年3月以來,11和12,所以我想通過3年,他們在特定年份的百分比(在總)有TYPE A,B,C的總和。 – user2103670

+0

是的,我不想讓事情變得複雜 - 現在3年應該足夠了。我想我們可以做動態旋轉或者什麼東西,有表的增長隨着數據的增長 – user2103670

回答

4

由於您使用的是SQL Server中,如果使用SQL Server 2005+那麼你可以使用旋轉功能得到結果。該解決方案實現了一個unpivot和一個透視過程來獲得結果。此結果的起點是按類型計算總百分比和總數:

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。最後,你可以將旋轉功能的值col

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

SUMIF可以在SQL複製與SUM(case statement)

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