1

複数の列に対してクリーンなピボットテーブルを取得しようとしています。

入力テーブルを作成する

create table #temp (
  ORDER_ID INT NOT NULL,
  TEST_PLAN INT NOT NULL,
  COLLECTION_TYPE INT NOT NULL,
  TEST_GRP INT NOT NULL,
  TEST INT NOT NULL
)

INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (1,1,2,1360942998,1360943100)
INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (2,1,2,1360943006,1360943079)
INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (1,2,2,1360942845,1360943173)
INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (2,2,2,1360942845,1360943134)
INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (3,2,2,1360942845,1360943189)
INSERT INTO #temp (ORDER_ID,TEST_PLAN,COLLECTION_TYPE,TEST_GRP,TEST) VALUES (1,3,2,1360942998,1360943100)

結果...

ORDER_ID PLAN COLLECTION_TYPE TEST_GRP   TEST        
-------- ---- --------------- ---------- ----------
1        1    2               1360942998 1360943100
2        1    2               1360943006 1360943079
1        2    1               1360942845 1360943173
2        2    1               1360942845 1360943134
3        2    1               1360942845 1360943189
1        3    2               1360942998 1360943100

ORDER_IDがCOLLECTION_TYPE、TEST_GRP、およびTEST列に追加されている次のものが欲しいです。

PLAN COLLECTION_TYPE_1 TEST_GRP_1 TEST_1     COLLECTION_TYPE_2 TEST_GRP_2 TEST_2     COLLECTION_TYPE_3 TEST_GRP_3 TEST_3
---- ----------------- ---------- ---------- ----------------- ---------- ---------- ----------------- ---------- ----------
1    2                 1360942998 1360943100 2                 1360943006 1360943079  NULL              NULL       NULL
2    1                 1360942845 1360943173 1                 1360942845 1360943134 1                 1360942845 1360943189
3    2                 1360942998 1360943100 NULL              NULL       NULL       NULL              NULL       NULL 

私はこれを持っていて、それは動作しますが、少しきれいなものを探していました(例えば、いくつかのヌル)。

DECLARE  @SQL  NVARCHAR(MAX),
         @Cols NVARCHAR(MAX)

SELECT @cols = STUFF((select ',
MAX(CASE WHEN [TEST_PLAN]=' + CONVERT(VARCHAR,[TEST_PLAN]) + ' AND [ORDER_ID] = ' + CONVERT(VARCHAR,[ORDER_ID]) +
' THEN [TEST_GRP] ELSE NULL END) AS [TEST_GRP_' + CONVERT(VARCHAR,[ORDER_ID]) + '],
MAX(CASE WHEN [TEST_PLAN]=' + CONVERT(VARCHAR,[TEST_PLAN]) + ' AND [ORDER_ID] = ' + CONVERT(VARCHAR,[ORDER_ID]) +
' THEN [TEST_GRP] ELSE NULL END) AS [TEST_' + CONVERT(VARCHAR,[ORDER_ID]) + '],
MAX(CASE WHEN [TEST_PLAN]=' + CONVERT(VARCHAR,[TEST_PLAN]) + ' AND [ORDER_ID] = ' + CONVERT(VARCHAR,[ORDER_ID]) +
' THEN [COLLECTION_TYPE] ELSE NULL END) AS [COLLECTION_TYPE_' + CONVERT(VARCHAR,[ORDER_ID]) + ']'
FROM #temp
ORDER BY [TEST_PLAN],[ORDER_ID] FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')

SET @SQL = 'SELECT TEST_PLAN,' + @Cols + ' FROM #Temp GROUP BY TEST_PLAN'

EXECUTE( @SQL)

出力があります...

TEST_PLAN   TEST_GRP_1  TEST_1      COLLECTION_TYPE_1 TEST_GRP_2  TEST_2      COLLECTION_TYPE_2 TEST_GRP_1  TEST_1      COLLECTION_TYPE_1 TEST_GRP_2  TEST_2      COLLECTION_TYPE_2 TEST_GRP_3  TEST_3      COLLECTION_TYPE_3 TEST_GRP_4  TEST_4      COLLECTION_TYPE_4 TEST_GRP_5  TEST_5      COLLECTION_TYPE_5 TEST_GRP_6  TEST_6      COLLECTION_TYPE_6 TEST_GRP_7  TEST_7      COLLECTION_TYPE_7 TEST_GRP_8  TEST_8      COLLECTION_TYPE_8 TEST_GRP_9  TEST_9      COLLECTION_TYPE_9 TEST_GRP_10 TEST_10     COLLECTION_TYPE_10 TEST_GRP_1  TEST_1      COLLECTION_TYPE_1
----------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ----------------- ----------- ----------- ------------------ ----------- ----------- -----------------
1           1360942998  1360942998  2                 1360943006  1360943006  2                 NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL               NULL        NULL        NULL
2           NULL        NULL        NULL              NULL        NULL        NULL              1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                 1360942845  1360942845  2                  NULL        NULL        NULL
3           NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL              NULL        NULL        NULL               1360942998  1360942998  2

上記のSQLに最も近い解決策を探しました。

ありがとうjlimited

4

1 に答える 1

2

希望する結果を得るには、UNPIVOTPIVOT関数の両方を使用する必要があります。はUNPIVOT列から値を取得して行に変換し、は行を取得PIVOTして列に変換し直します。

最初に静的バージョンまたはハードコードされたバージョンのクエリを使用してから、動的SQLに変換する方が簡単な場合があります。静的バージョンは次のようになります。

select [Plan],
  Isnull(COLLECTION_TYPE_1, '') COLLECTION_TYPE_1, 
  Isnull(TEST_GRP_1, '') TEST_GRP_1, 
  Isnull(TEST_1, '') TEST_1,
  Isnull(COLLECTION_TYPE_2, '') COLLECTION_TYPE_2, 
  Isnull(TEST_GRP_2, '') TEST_GRP_2, 
  Isnull(TEST_2, '') TEST_2,
  Isnull(COLLECTION_TYPE_3, '') COLLECTION_TYPE_3, 
  Isnull(TEST_GRP_3, '') TEST_GRP_3, 
  Isnull(TEST_3, '') TEST_3
from
(
  select [PLAN], col + '_'+ cast(ORDER_ID as varchar(50)) col, value
  from
  (
    select ORDER_ID,[PLAN],COLLECTION_TYPE,TEST_GRP,TEST
    from temp
  ) s
  unpivot
  (
    value
    for col in (COLLECTION_TYPE,TEST_GRP,TEST)
  ) unpiv
) src
pivot
(
  max(value)
  for col in (COLLECTION_TYPE_1, TEST_GRP_1, TEST_1,
              COLLECTION_TYPE_2, TEST_GRP_2, TEST_2,
              COLLECTION_TYPE_3, TEST_GRP_3, TEST_3)
) piv

SQL FiddlewithDemoを参照してください。

静的バージョンを入手したら、これを動的SQLに簡単に変換できます。null動的SQLを生成するときに、値を空の文字列またはをクリーンアップする別の値に置き換える列のリストを作成できますnulls。動的SQLコードは次のとおりです。

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

select @cols = STUFF((SELECT ',' + QUOTENAME(col + '_'+ cast(ORDER_ID as varchar(50))) 
                    from temp t
                    cross apply 
                    (
                      select 'COLLECTION_TYPE' col, 1 SortOrder
                      union all
                      select 'TEST_GRP' col, 2 SortOrder
                      union all
                      select 'TEST' col, 3 SortOrder
                    ) c
                    group by col, ORDER_ID, sortorder
                    order by ORDER_ID, sortorder
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNames = STUFF((SELECT ', IsNull(' + QUOTENAME(col + '_'+ cast(ORDER_ID as varchar(50)))+', '''') as '+QUOTENAME(col + '_'+ cast(ORDER_ID as varchar(50)))
                    from temp t
                    cross apply 
                    (
                      select 'COLLECTION_TYPE' col, 1 SortOrder
                      union all
                      select 'TEST_GRP' col, 2 SortOrder
                      union all
                      select 'TEST' col, 3 SortOrder
                    ) c
                    group by col, ORDER_ID, sortorder
                    order by ORDER_ID, sortorder
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT [PLAN],' + @colsNames + ' from 
             (
                select [PLAN], col + ''_''+ cast(ORDER_ID as varchar(50)) col, value
                from
                (
                  select ORDER_ID,[PLAN],COLLECTION_TYPE,TEST_GRP,TEST
                  from temp
                ) s
                unpivot
                (
                  value
                  for col in (COLLECTION_TYPE,TEST_GRP,TEST)
                ) unpiv
            ) src
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute(@query)

SQL FiddlewithDemoを参照してください

どちらも結果を出します。

| PLAN | COLLECTION_TYPE_1 | TEST_GRP_1 |     TEST_1 | COLLECTION_TYPE_2 | TEST_GRP_2 |     TEST_2 | COLLECTION_TYPE_3 | TEST_GRP_3 |     TEST_3 |
--------------------------------------------------------------------------------------------------------------------------------------------------
|    1 |                 2 | 1360942998 | 1360943100 |                 2 | 1360943006 | 1360943079 |                 0 |          0 |          0 |
|    2 |                 1 | 1360942845 | 1360943173 |                 1 | 1360942845 | 1360943134 |                 1 | 1360942845 | 1360943189 |
|    3 |                 2 | 1360942998 | 1360943100 |                 0 |          0 |          0 |                 0 |          0 |          0 |
于 2013-02-26T04:43:52.180 に答える