web-dev-qa-db-ja.com

動的ピボット:1か月あたりの売上の合計

私のテーブルは次のようなものです:

Sitecode    Month  Amount
--------    -----  ------
XX          Jan     1000
XX          Jan     3000
XX          Apr     3000
XX          Apr     1000

私が欲しいのは、このような結果を表示することです:

Sitecode    MonthJAN   MonthAPR
--------    --------   --------
XX          4000       4000
4
user16947

他の人が言っているように、これは PIVOT として知られています。データを行からデータの列に変換する方法はいくつかあります。

事前に値がわかっている場合は、値をハードコーディングできます。 PIVOT関数の前に、CASEステートメントで集計関数を使用します。

Aggregate/CASEバージョン:

select sitecode,
  sum(case when [month] = 'Jan' then amount else 0 end) MonthJan,
  sum(case when [month] = 'Apr' then amount else 0 end) MonthApr
from yourtable
group by sitecode;

SQL Fiddle with Demo を参照してください。

PIVOT関数はSQL Server 2005で使用できるようになったため、そのバージョンまたはそれ以降のバージョンを使用している場合は、それをデータに適用できます。

静的PIVOT:

select *
from
(
  select sitecode,
    [month],
    amount
  from yourtable
) src
pivot
(
  sum(amount)
  for month in (Jan, Apr)
) piv;

参照 SQL Fiddleデモあり

上記の2つのバージョンは、事前に値がわかっている場合に最適です。そうでない場合は、動的SQLを使用して結果を作成します。

ダイナミックPIVOT:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(month) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT sitecode,' + @cols + ' from 
             (
                select sitecode, [month], amount
                from yourtable
            ) x
            pivot 
            (
                sum(amount)
                for month in (' + @cols + ')
            ) p '

execute(@query)

参照 SQL Fiddleデモあり

これの3つのバージョンはすべて同じ結果を返します。

| SITECODE |  JAN |  APR |
--------------------------
|       XX | 4000 | 4000 |
18
Taryn

マーティン・スミスが言ったように、明示的なPIVOTが参照されていても、このようなものであっても、データをピボットする必要があります (SQL Fiddle)

SELECT SiteCode
   , SUM(Case When Month='Jan' Then Amount Else 0 End) MonthJan
   , SUM(Case When Month='Apr' Then Amount Else 0 End) MonthApr
FROM Result GROUP BY SiteCode;
9
Leigh Riffel