3

複数の繰り返しグループを持つ結果セット (テーブルに挿入される) を取得しようとしています。これは、私が始めたデータの非常に単純化されたバージョンを示すスクリプトです。

CREATE TABLE #Aggregate(
    StoreKey int ,
    NumberOfDaysBack int ,
    ThisYearGrossTransactions int ,
    ThisYearGrossPrice money ,
    LastYearGrossTransactions int ,
    LastYearGrossPrice money 
) 
GO
INSERT #Aggregate VALUES (10134, 7, 198, 71324.3600, 248, 95889.6089)
INSERT #Aggregate VALUES (10131, 7, 9, 1299.8300, 3, 662.5700)
INSERT #Aggregate VALUES (10132, 7, 57, 11029.5300, 56, 6848.3800)
INSERT #Aggregate VALUES (10130, 7, 6, 429.3100, 15, 1606.1100)
INSERT #Aggregate VALUES (10134, 28, 815, 339315.9265, 822, 342834.2365)
INSERT #Aggregate VALUES (10131, 28, 29, 5725.4900, 8, 1938.4100)
INSERT #Aggregate VALUES (10132, 28, 262, 42892.5476, 269, 37229.2600)
INSERT #Aggregate VALUES (10130, 28, 62, 6427.7072, 93, 13428.0000)

次に、次のように、NumberOfDaysBack のセットごとに個別のデータ セットを表示したいと思います。

StoreKey    ThisYearLast7GrossTransactions ThisYearLast7GrossPrice LastYearLast7GrossTransactions LastYearLast7GrossPrice ThisYearLast28GrossTransactions ThisYearLast28GrossPrice LastYearLast28GrossTransactions LastYearLast28GrossPrice
----------- ------------------------------ ----------------------- ------------------------------ ----------------------- ------------------------------- ------------------------ ------------------------------- ------------------------
10130       6                              429.31                  15                             1606.11                 62                              6427.7072                93                              13428.00
10131       9                              1299.83                 3                              662.57                  29                              5725.49                  8                               1938.41
10132       57                             11029.53                56                             6848.38                 262                             42892.5476               269                             37229.26
10134       198                            71324.36                248                            95889.6089              815                             339315.9265              822                             342834.2365

このクエリで上記の結果セットを取得できました。

-- (using this Common Table expression as a shortcut, there's actually a dimention table
;with Store as (select distinct StoreKey from #Aggregate)
Select
    Store.StoreKey
    ,ThisYearLast7GrossTransactions = DaysBack7.ThisYearGrossTransactions
    ,ThisYearLast7GrossPrice = DaysBack7.ThisYearGrossPrice
    ,LastYearLast7GrossTransactions = DaysBack7.LastYearGrossTransactions
    ,LastYearLast7GrossPrice = DaysBack7.LastYearGrossPrice
    ,ThisYearLast28GrossTransactions = DaysBack28.ThisYearGrossTransactions
    ,ThisYearLast28GrossPrice = DaysBack28.ThisYearGrossPrice
    ,LastYearLast28GrossTransactions = DaysBack28.LastYearGrossTransactions
    ,LastYearLast28GrossPrice = DaysBack28.LastYearGrossPrice    
from Store 
    join #Aggregate DaysBack7
        on Store .StoreKey = DaysBack7.StoreKey
        and DaysBack7 .NumberOfDaysBack = 7
    join #Aggregate DaysBack28
        on Store .StoreKey = DaysBack28.StoreKey
        and DaysBack28 .NumberOfDaysBack = 28
order by Store.StoreKey

ただし、実際のデータ セットははるかに複雑で、変更される可能性のある NumberOfDaysBack やメトリックが多数あるため、各フィールドに明示的に名前を付ける必要なく、ピボット ステートメントを使用してこれを実行できるようにしたいと考えています。

これは可能ですか?アイデアをありがとう!

4

2 に答える 2

4

UNPIVOTと の両方を使用して、必要な結果を得ることができますPIVOT

select *
from
(
  select storekey, 
    value, col +'Last'+ cast(numberofdaysback as varchar(20)) + 'Days' new_col
  from
  (
    select storekey,
      numberofdaysback,
      cast(ThisYearGrossTransactions as decimal(20,5)) ThisYearGrossTransactions,
      cast(ThisYearGrossPrice as decimal(20,5)) ThisYearGrossPrice,
      cast(LastYearGrossTransactions as decimal(20,5)) LastYearGrossTransactions,
      cast(LastYearGrossPrice as decimal(20,5)) LastYearGrossPrice    
    from aggregate
  ) un
  unpivot
  (
    value
    for col in (ThisYearGrossTransactions, ThisYearGrossPrice,
                LastYearGrossTransactions, LastYearGrossPrice)
  ) unpiv
) src
pivot
(
  sum(value)
  for new_col in ([ThisYearGrossTransactionsLast7Days], [ThisYearGrossPriceLast7Days],
                  [LastYearGrossTransactionsLast7Days], [LastYearGrossPriceLast7Days],
                  [ThisYearGrossTransactionsLast28Days], [ThisYearGrossPriceLast28Days],
                  [LastYearGrossTransactionsLast28Days], [LastYearGrossPriceLast28Days])
) piv;

デモで SQL Fiddle を参照してください

は、 、、 およびUNPIVOTの列の値を取得し、それらを複数の行を持つ 1 つの列に変換します。ThisYearGrossTransactionsThisYearGrossPriceLastYearGrossTransactionsLastYearGrossPrice

select storekey, 
  value, col +'Last'+ cast(numberofdaysback as varchar(20)) + 'Days' new_col
from
(
  select storekey,
    numberofdaysback,
    cast(ThisYearGrossTransactions as decimal(20,5)) ThisYearGrossTransactions,
    cast(ThisYearGrossPrice as decimal(20,5)) ThisYearGrossPrice,
    cast(LastYearGrossTransactions as decimal(20,5)) LastYearGrossTransactions,
    cast(LastYearGrossPrice as decimal(20,5)) LastYearGrossPrice    
  from aggregate
) un
unpivot
(
  value
  for col in (ThisYearGrossTransactions, ThisYearGrossPrice,
              LastYearGrossTransactions, LastYearGrossPrice)
) unpiv

デモで SQL Fiddle を参照してください

の要件はUNPIVOT、すべてのデータ型が同じである必要があるため、いずれかcastまたはconvert任意の値に適用する必要があることです。次に、データに、各レコードに をPIVOT追加して新しい列名を作成しました。これらは、クエリ numberofdaysbackの一部で使用される値です。PIVOT

最終結果は次のとおりです。

| STOREKEY | THISYEARGROSSTRANSACTIONSLAST7DAYS | THISYEARGROSSPRICELAST7DAYS | LASTYEARGROSSTRANSACTIONSLAST7DAYS | LASTYEARGROSSPRICELAST7DAYS | THISYEARGROSSTRANSACTIONSLAST28DAYS | THISYEARGROSSPRICELAST28DAYS | LASTYEARGROSSTRANSACTIONSLAST28DAYS | LASTYEARGROSSPRICELAST28DAYS |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|    10130 |                                  6 |                      429.31 |                                 15 |                     1606.11 |                                  62 |                    6427.7072 |                                  93 |                        13428 |
|    10131 |                                  9 |                     1299.83 |                                  3 |                      662.57 |                                  29 |                      5725.49 |                                   8 |                      1938.41 |
|    10132 |                                 57 |                    11029.53 |                                 56 |                     6848.38 |                                 262 |                   42892.5476 |                                 269 |                     37229.26 |
|    10134 |                                198 |                    71324.36 |                                248 |                  95889.6089 |                                 815 |                  339315.9265 |                                 822 |                  342834.2365 |

上記の静的バージョンは、既知の数の値NumberOfDaysBackがある場合にうまく機能しますが、多くの値の数が不明な場合は、これの動的バージョンを使用できます。

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)

select @colsUnpivot = stuff((select ','+quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('Aggregate') and
               C.name not in ('StoreKey', 'NumberOfDaysBack')
         for xml path('')), 1, 1, '')

select @colsPivot = STUFF((SELECT  ',' 
                      + quotename(c.name +'Last'
                         + cast(a.NumberOfDaysBack as varchar(10)) +'Days')
                    from Aggregate a
                    cross apply sys.columns  C
                   where C.object_id = object_id('Aggregate') and
                         C.name not in ('StoreKey', 'NumberOfDaysBack')
                   group by c.name, a.NumberOfDaysBack
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
  = 'select *
      from
      (
        select storekey, 
            value, col +''Last''+ cast(numberofdaysback as varchar(20)) + ''Days'' new_col
        from 
        (
          select storekey,
            numberofdaysback,
            cast(ThisYearGrossTransactions as decimal(20,5)) ThisYearGrossTransactions,
            cast(ThisYearGrossPrice as decimal(20,5)) ThisYearGrossPrice,
            cast(LastYearGrossTransactions as decimal(20,5)) LastYearGrossTransactions,
            cast(LastYearGrossPrice as decimal(20,5)) LastYearGrossPrice    
          from aggregate
        ) x
        unpivot
        (
          value
          for col in ('+ @colsunpivot +')
        ) u
      ) x1
      pivot
      (
        sum(value)
        for new_col in ('+ @colspivot +')
      ) p'

exec(@query)

デモで SQL Fiddle を参照してください

結果は、両方のクエリで同じになります。

于 2012-11-20T10:43:49.960 に答える
1

あなたが達成したい結果は、PIVOTを使用して次のようなものになる可能性があります。

SELECT StoreKey, 
[1] AS ThisYearGrossTransactionsFor7Days, 
[2] AS ThisYearGrossPriceFor7Days, 
[3] AS LastYearGrossTransactionsFor7Days, 
[4] AS LastYearGrossPriceFor7Days, 
[5] AS ThisYearGrossTransactionsFor28Days, 
[6] AS ThisYearGrossPriceFor28Days, 
[7] AS LastYearGrossTransactionsFor28Days, 
[8] AS LastYearGrossPriceFor28Days
FROM
(SELECT StoreKey,ThisYearGrossTransactions AS Value, 1 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 7
UNION ALL 
SELECT StoreKey,ThisYearGrossPrice AS Value, 2 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 7
UNION ALL 
SELECT StoreKey,LastYearGrossTransactions AS Value, 3 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 7
UNION ALL 
SELECT StoreKey,LastYearGrossPrice AS Value, 4 AS TypeOfAggreagate
FROM #Aggregate WHERE NumberOfDaysBack = 7
UNION ALL
SELECT StoreKey,ThisYearGrossTransactions AS Value, 5 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 28
UNION ALL 
SELECT StoreKey,ThisYearGrossPrice AS Value, 6 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 28
UNION ALL 
SELECT StoreKey,LastYearGrossTransactions AS Value, 7 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 28
UNION ALL 
SELECT StoreKey,LastYearGrossPrice AS Value, 8 AS TypeOfAggregate
FROM #Aggregate WHERE NumberOfDaysBack = 28) p
PIVOT(
SUM(Value)
FOR TypeOfAggregate IN ([1], [2], [3], [4], [5], [6], [7], [8])
) AS pvt
ORDER BY StoreKey

このため、ご覧の#Aggregateとおり、を別の形式に変換し、値を「入力」する必要があります(TypeOfAggregate)。

しかし、このために、あなたは書くことができますDynamic PIVOTこれがStackOwerflowのスレッドです

于 2012-11-19T13:21:05.703 に答える