行から列への変換は PIVOT と呼ばれ、SQL Server でこれを行うにはいくつかの方法があります。
集計 / CASE: CASE 式と共に集計関数を使用できます。これはrow_number()
、テーブル内のデータにウィンドウ関数を適用することで機能します。
select h_company_id, company_nm,
max(case when seq = 1 then mainphone1 end) mainphone1,
max(case when seq = 1 then phone_cnt end) phone_cnt1,
max(case when seq = 2 then mainphone1 end) mainphone2,
max(case when seq = 2 then phone_cnt end) phone_cnt2
from
(
select h_company_id, company_nm, mainphone1, phone_cnt,
row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
) d
group by h_company_id, company_nm;
SQL Fiddle with Demoを参照してください。CASE 式は、シーケンス番号の値が 1 か 2 かをチェックし、データを列に配置します。
UNPIVOT / PIVOT: 2 つの列に存在するデータを PIVOT したいので、最初に列mainphone1
とphone_cnt
列を UNPIVOT して同じ列に取得してから、PIVOT 関数を適用します。
UNPIVOT コードは次のようになります。
select h_company_id, company_nm,
col+cast(seq as varchar(10)) col,
value
from
(
select h_company_id, company_nm,
cast(mainphone1 as varchar(15)) mainphone,
cast(phone_cnt as varchar(15)) phone_cnt,
row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
) d
unpivot
(
value
for col in (mainphone, phone_cnt)
) unpiv;
デモを参照してください。このクエリは、次の形式でデータを取得します。
| H_COMPANY_ID | COMPANY_NM | COL | VALUE |
---------------------------------------------------------------
| 11043 | 3I Group PLC | mainphone1 | 2079753731 |
| 11043 | 3I Group PLC | phone_cnt1 | 15 |
| 11043 | 3I Group PLC | mainphone2 | 2079757115 |
| 11043 | 3I Group PLC | phone_cnt2 | 1 |
| 20816 | 800 Flowers | mainphone1 | 5162377000 |
次に、 PIVOT 関数を の値に適用しますcol
。
select h_company_id, company_nm,
mainphone1, phone_cnt1, mainphone2, phone_cnt2
from
(
select h_company_id, company_nm,
col+cast(seq as varchar(10)) col,
value
from
(
select h_company_id, company_nm,
cast(mainphone1 as varchar(15)) mainphone,
cast(phone_cnt as varchar(15)) phone_cnt,
row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
) d
unpivot
(
value
for col in (mainphone, phone_cnt)
) unpiv
) src
pivot
(
max(value)
for col in (mainphone1, phone_cnt1, mainphone2, phone_cnt2)
) piv;
SQL Fiddle with Demoを参照してください。
複数の結合:テーブルに複数回結合して結果を取得することもできます。
;with cte as
(
select h_company_id, company_nm, mainphone1, phone_cnt,
row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
)
select c1.h_company_id,
c1.company_nm,
c1.mainphone1,
c1.phone_cnt phone_cnt1,
c2.mainphone1 mainphone2,
c2.phone_cnt phone_cnt2
from cte c1
left join cte c2
on c1.h_company_id = c2.h_company_id
and c2.seq = 2
where c1.seq = 1;
SQL Fiddle with Demoを参照してください。
動的 SQL:最後に、変換したい値の数が不明な場合は、動的 SQL を実装して結果を取得する必要があります。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(seq as varchar(10)))
from
(
select row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
) d
cross apply
(
select 'mainphone', 1 union all
select 'phone_cnt', 2
) c (col, so)
group by seq, so, col
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT h_company_id, company_nm,' + @cols + '
from
(
select h_company_id, company_nm,
col+cast(seq as varchar(10)) col,
value
from
(
select h_company_id, company_nm,
cast(mainphone1 as varchar(15)) mainphone,
cast(phone_cnt as varchar(15)) phone_cnt,
row_number() over(partition by h_company_id order by mainphone1) seq
from yourtable
) d
unpivot
(
value
for col in (mainphone, phone_cnt)
) unpiv
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
execute(@query)
SQL Fiddle with Demoを参照してください。すべて結果が得られます。
| H_COMPANY_ID | COMPANY_NM | MAINPHONE1 | PHONE_CNT1 | MAINPHONE2 | PHONE_CNT2 |
-----------------------------------------------------------------------------------------
| 20820 | 1st Source Corp. | 5742353000 | 3 | (null) | (null) |
| 20821 | 1st United Bancorp | 5613633400 | 2 | (null) | (null) |
| 20824 | 3D Systems Inc. | 8033273900 | 4 | 8033464010 | 1 |
| 11043 | 3I Group PLC | 2079753731 | 15 | 2079757115 | 1 |
| 20816 | 800 Flowers | 5162377000 | 3 | 5162377131 | 1 |