1

この構造のテーブルにデータがあります。

Region | Date       | Value

A      | 01/01/2014 |    100

A      | 01/20/2014 |     50

A      | 01/02/2014 |    200

A      | 01/05/2014 |    300

B      | 01/01/2014 |    50

B      | 02/15/2014 |    70

B      | 02/25/2014 |    50

C      | 05/02/2014 |    70

T-SQL クエリを使用して、次のようなピボット ビューを作成しようとしています。

Region | Jan-2014 | Feb-2014 | Mar-014 | Apr-2014 | May-2014 | -> thru desired month-year

A      |    150   |   200    |   0     |     0    |    300   |

B      |     50   |   120    |   0     |     0    |      0   |

C      |      0   |     0    |   0     |     0    |     70   |

特定の地域の同じ月の複数の値を集計する必要があることに注意してください レコードのない月は、値がゼロの列として表示されます (例: 3 月と 4 月)

ピボット オプションや withroll up などを使用するのに疲れましたが、これを機能させることができないようです。

ありがとうございました。

4

1 に答える 1

3

これらの月の結果がないのは、列にピボットする日付がないためです。

これを行うにはいくつかの方法があります。IN列が表示されるように、クエリの一部にすべての日付値をハードコーディングできます。

select Region,
  isnull([Jan-2014], 0) [Jan-2014], isnull([Feb-2014], 0) [Feb-2014], 
  isnull([Mar-2014], 0) [Mar-2014], isnull([Apr-2014], 0) [Apr-2014],
  isnull([May-2014], 0) [May-2014], isnull([Jun-2014], 0) [Jun-2014], 
  isnull([Jul-2014], 0) [Jul-2014], isnull([Aug-2014], 0) [Aug-2014],
  isnull([Sep-2014], 0) [Sep-2014], isnull([Oct-2014], 0) [Oct-2014], 
  isnull([Nov-2014], 0) [Nov-2014], isnull([Dec-2014], 0) [Dec-2014]
from 
(
  select left(datename(month, t.date), 3) +'-'
            + cast(year(t.date) as char(4)) monthYear,
    t.region,
    t.value
  from yt t
) src
pivot
(
  sum(value)
  for monthYear in ([Jan-2014], [Feb-2014], [Mar-2014], [Apr-2014],
                    [May-2014], [Jun-2014], [Jul-2014], [Aug-2014],
                    [Sep-2014], [Oct-2014], [Nov-2014], [Dec-2014])
) piv;

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

これを行う別の方法は、クエリで使用できる日付のテーブルを作成することです。LEFT JOIN作成したら、テーブルにa を使用して、表示するすべての日付を返すことができます。再帰クエリを作成して PIVOT クエリでこのリストを生成するか、テーブルに日付のリストを入力することができます。再帰クエリは次のようになります。

;with dates (startDate, endDate) as 
(
  select min(date), cast('2014-12-31' as date)
  from yt
  union all
  select dateadd(m, 1, startDate), enddate
  from dates
  where month(startDate) + 1 <= month(enddate)
)
select startDate
from dates;

SQL Fiddle with Demoを参照してください。これを PIVOT に結合すると、クエリは次のようになります。

select *
from 
(
  select left(datename(month, d.startdate), 3) +'-'
            + cast(year(d.startdate) as char(4)) monthYear,
    t.region,
    t.value
  from dates d
  left join yt t
    on month(d.startdate) = month(t.date)
    and year(d.startdate) = year(t.date)
) src
pivot
(
  sum(value)
  for monthYear in ([Jan-2014], [Feb-2014], [Mar-2014], [Apr-2014],
                    [May-2014], [Jun-2014], [Jul-2014], [Aug-2014],
                    [Sep-2014], [Oct-2014], [Nov-2014], [Dec-2014])
) piv
where region is not null;

SQL Fiddle with Demoを参照してください。これを PIVOT クエリの一部として使用できますが、INPIVOT の句ですべての日付を手動でコーディングする必要があります。

このクエリの動的 SQL バージョンを使用して、必要に応じて日付を変更することをお勧めします。動的バージョンは次のようになります。

DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @startdate datetime = '2014-01-01',
    @enddate datetime = '2014-12-01'

;with dates (startDate, endDate) as 
(
  select @startdate, @enddate
  from yt
  union all
  select dateadd(m, 1, startDate), enddate
  from dates
  where dateadd(m, 1, startDate) <= enddate
)
select @cols = STUFF((SELECT ',' + QUOTENAME(left(datename(month, d.startdate), 3) +'-'
                                                      + cast(year(d.startdate) as char(4))) 
                    from dates d
                    -- where startdate >= '2014-01-01' and startdate <= '2014-06-01'
                    group by d.startdate
                    order by d.startdate
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,''),
    @colsNull = STUFF((SELECT ', isnull(' + QUOTENAME(left(datename(month, d.startdate), 3) +'-'
                                                      + cast(year(d.startdate) as char(4)))+', 0) as '+QUOTENAME(left(datename(month, d.startdate), 3) +'-'
                                                      + cast(year(d.startdate) as char(4)))
                    from dates d
                    -- where startdate >= '2014-01-01' and startdate <= '2014-06-01'
                    group by d.startdate
                    order by d.startdate
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
from dates

set @query = 'SELECT region, ' + @colsNull + ' from 
             (
                  select left(datename(month, t.date), 3) +''-''
                            + cast(year(t.date) as char(4)) monthYear,
                    t.region,
                    t.value
                  from yt t
            ) x
            pivot 
            (
                sum(value)
                for monthyear in (' + @cols + ')
            ) p '

execute(@query);

SQL Fiddle with Demoを参照してください。このバージョンでは、再帰 CTE を使用して、動的 SQL 文字列で使用される日付のリストを生成します。表示されている月のデータ テーブルが存在しない場合でも、新しい列が作成されます。

これにより、次の結果が得られます。

| REGION | JAN-2014 | FEB-2014 | MAR-2014 | APR-2014 | MAY-2014 | JUN-2014 | JUL-2014 | AUG-2014 | SEP-2014 | OCT-2014 | NOV-2014 | DEC-2014 |
----------------------------------------------------------------------------------------------------------------------------------------------
|      A |      650 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |
|      B |       50 |      120 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |
|      C |        0 |        0 |        0 |        0 |       70 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |
于 2013-05-09T11:50:53.757 に答える