1

ここに画像の説明を入力 これはExcelで簡単に実行できるはずですが、この種の計算をSQLで実行したいと考えています。を使用してGROUP BYOVER()1 年の SUM と % を計算できます。しかし、3 年分のデータを一度に提示できませんでした。どんな助けでも大歓迎です。

4

3 に答える 3

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を参照してください。これにより、ピボットしたい複数の列を含む結果が得られるため、CROSS APPLY を使用してデータを複数の行にピボット解除できます。

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);

デモを参照してください。最後に、 PIVOT 関数を の値に適用できます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;

デモを参照してください。静的バージョンと動的バージョンの両方で結果が得られます。

| 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 |
于 2013-07-29T19:13:02.847 に答える
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
于 2013-07-29T19:00:06.527 に答える
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 フィドルのデモ

于 2013-07-29T18:52:00.083 に答える