9

個人によって実行された活動の詳細を保持するテーブルがあります。このテーブルの内容は次のようになります。

| | 人 | カテゴリー | 活動 |
--------------------------------------
| | ユーザー名1 | X | X1 |
| | ユーザー名1 | よ | Y1 |
| | ユーザー名1 | Z | Z1 |

次のようなものを生成できる SQL クエリが必要です。

| | 人 | カテゴリ 1 | Cat1_Act|Cat2 | Cat2_Act| カテゴリー3 | Cat3_Act |
-------------------------------------------------- -------------
| | ユーザー名1 | X | X1 | よ | Y1 | Z | Z1 |

これを達成するためにPIVOTを使用できるという多くの投稿を読んだことは理解していますが、ほとんどのソリューションは多くの場合、「X」、「Y」、「Z」などの値を使用するため、必要なものに近いソリューションを見つけることができませんでした(私の例のテーブルでは)テーブルヘッダーとしてですが、理想的には新しい列を保持するテーブルヘッダーの名前を指定できるようにしたいです(これがすべて理にかなっていて、誰かが助けてくれることを願っています:-))

4

2 に答える 2

11

目的の結果を得るには、いくつかの方法があります。列に PIVOT する値の数が限られている場合は、いくつかの異なる方法でクエリをハードコーディングできます。

CASE を使用した集計関数:

select 
  person,
  max(case when seq = 1 then category end) Cat1,
  max(case when seq = 1 then activity end) Cat1_Act,
  max(case when seq = 2 then category end) Cat2,
  max(case when seq = 2 then activity end) Cat2_Act,
  max(case when seq = 3 then category end) Cat3,
  max(case when seq = 3 then activity end) Cat3_Act
from
(
  select person, category, activity,
    row_number() over(partition by person
                      order by category) seq
  from yourtable
) d
group by person;

SQL Fiddle with Demoを参照してください。ユーザーごとに各カテゴリにシーケンスまたは row_number を割り当てることで、この行番号を使用して行を列に変換できます。

静的ピボット:

PIVOT 関数を適用する場合は、最初に列categoryactivity列のピボットを解除して複数の行にしてから、ピボット関数を適用することをお勧めします。

;with cte as
(
  select person, category, activity,
    row_number() over(partition by person
                      order by category) seq
  from yourtable
)
select person,
  cat1, cat1_act, 
  cat2, cat2_act,
  cat3, cat3_act
from
(
  select t.person, 
    col = case 
     when c.col = 'cat' then col+cast(seq as varchar(10))
      else 'cat'+cast(seq as varchar(10))+'_'+col
    end,
    value
  from cte t
  cross apply
 (
    select 'cat', category union all
    select 'act', activity
  ) c (col, value)
) d
pivot
(
  max(value)
  for col in (cat1, cat1_act, cat2, cat2_act,
              cat3, cat3_act)
) piv;

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

動的 PIVOT:最後に、値の数が不明な場合は、動的 SQL を使用して結果を取得できます。

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

select @cols = STUFF((SELECT ',' 
                          + QUOTENAME(case 
                                       when d.col = 'cat' then col+cast(seq as varchar(10))
                                        else 'cat'+cast(seq as varchar(10))+'_'+col end) 
                    from 
                    (
                      select row_number() over(partition by person
                                                order by category) seq
                      from yourtable
                    ) t
                    cross apply
                    (
                      select 'cat', 1 union all
                      select 'act', 2
                    ) d (col, so)
                    group by col, so, seq
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT person, ' + @cols + ' 
            from 
            (
              select t.person, 
                col = case 
                 when c.col = ''cat'' then col+cast(seq as varchar(10))
                  else ''cat''+cast(seq as varchar(10))+''_''+col
                end,
                value
              from 
              (
                select person, category, activity,
                  row_number() over(partition by person
                                    order by category) seq
                from yourtable
              ) t
              cross apply
             (
                select ''cat'', category union all
                select ''act'', activity
              ) c (col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

SQL Fiddle with Demoを参照してください。すべてのバージョンで結果が得られます。

|    PERSON | CAT1 | CAT1_ACT | CAT2 | CAT2_ACT | CAT3 | CAT3_ACT |
| Username1 |    X |       X1 |    Y |       Y1 |    Z |       Z1 |
于 2013-08-29T15:46:59.900 に答える
3

これは簡単な例です

 SELECT 
       Person,  
       MAX(CASE Category WHEN 'X' THEN Activity ELSE 0 END) AS 'X'
       MAX(CASE Category WHEN 'Y' THEN Activity ELSE 0 END) AS 'Y'
       MAX(CASE Category WHEN 'Z' THEN Activity ELSE 0 END) AS 'Z' 
    FROM mytable
    GROUP BY Person
于 2013-08-29T15:46:39.350 に答える