pivot
このタイプのデータ変換は、aと関数の両方で実行する必要がありunpivot
ます。訪問は不明になるため、動的SQLを使用することをお勧めします。ただし、最初に、プロセスがどのように機能するかを理解しやすくするために、値をハードコーディングしてクエリを作成する方法を示します。
まず、値が同じ列になるようにと列を作成UNPIVOT
する必要があります。これは、クエリまたはunpivot関数を使用して実行できます。date
weight
UNION ALL
UNPIVOT:
select patientid, name, rn, col, value
from
(
select p.patientid, p.name, convert(char(5), v.date, 110) date,
cast(v.weight as char(5)) weight,
row_number() over(partition by PatientID_FK order by date) rn
from patients p
left join visits v
on p.patientid = v.PatientID_FK
) src
unpivot
(
value
for col in (date, weight)
) unpiv
SQL FiddlewithDemoを参照してください。このクエリの結果は、日付列と重み列の両方の値を複数の行を持つ単一の列に配置します。レコードにaを適用したrow_number()
ので、訪問するたびにどのような値になるかがわかります。
| PATIENTID | NAME | RN | COL | VALUE |
-------------------------------------------
| 1 | James | 1 | date | 01-01 |
| 1 | James | 1 | weight | 220 |
| 1 | James | 2 | date | 02-01 |
| 1 | James | 2 | weight | 210 |
ピボット:
次のステップはPIVOT
、列の項目に関数を適用するcol
ことですが、最初に名前を変更して、必要な名前が付けられるようにする必要があります。
これを行うには、SELECT
ステートメントを少し変更して、行番号を列名に追加します。
select patientid, name, 'Visit'+col + cast(rn as varchar(10)) new_col,
value
from ...
これにより、列として必要な名前である新しい名前が得られます。
Visitdate1
Visitweight1
Visitdate2
Visitweight2
データに対してPIVOT
、値をハードコーディングすると、クエリは次のようになります。
select *
from
(
select patientid, name, 'Visit'+col + cast(rn as varchar(10)) new_col,
value
from
(
select p.patientid, p.name, convert(char(5), v.date, 110) date,
cast(v.weight as char(5)) weight,
row_number() over(partition by PatientID_FK order by date) rn
from patients p
left join visits v
on p.patientid = v.PatientID_FK
) src
unpivot
(
value
for col in (date, weight)
) unpiv
) s1
pivot
(
max(value)
for new_col in (Visitdate1,Visitweight1,
Visitdate2,Visitweight2)
) piv
SQL FiddlewithDemoを参照してください。
動的ピボット:
これがどのように設定されるかの背後にあるロジックを説明したので、動的SQLを使用してこれと同じプロセスを実装する必要があります。動的SQLバージョンは次のようになります。
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('visits') and
C.name not in ('PatientID_FK')
for xml path('')), 1, 1, '')
select @colsPivot = STUFF((SELECT ',' + quotename('Visit'+c.name
+ cast(v.rn as varchar(10)))
from
(
select row_number() over(partition by PatientID_FK order by date) rn
from visits
) v
cross apply sys.columns as C
where C.object_id = object_id('visits') and
C.name not in ('PatientID_FK')
group by c.name, v.rn
order by v.rn
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'select *
from
(
select patientid, name, ''Visit''+col + cast(rn as varchar(10)) new_col,
value
from
(
select p.patientid, p.name, convert(char(5), v.date, 110) date,
cast(v.weight as char(5)) weight,
row_number() over(partition by PatientID_FK order by date) rn
from patients p
left join visits v
on p.patientid = v.PatientID_FK
) x
unpivot
(
value
for col in ('+ @colsunpivot +')
) u
) x1
pivot
(
max(value)
for new_col in ('+ @colspivot +')
) p'
exec(@query)
SQL FiddlewithDemoを参照してください
両方のバージョンの結果は次のとおりです。
| PATIENTID | NAME | VISITDATE1 | VISITWEIGHT1 | VISITDATE2 | VISITWEIGHT2 |
-----------------------------------------------------------------------------
| 1 | James | 01-01 | 220 | 02-01 | 210 |