1. ホーム
  2. sql

[解決済み] SQL Server : 列を行に変換する

2022-03-14 02:01:31

質問

列を行に変換するためのエレガントな(または任意の)ソリューションを探しています。

以下はその例です。次のようなスキーマを持つテーブルがあります。

[ID] [EntityID] [Indicator1] [Indicator2] [Indicator3] ... [Indicator150]

以下は、結果として得たいものです。

[ID] [EntityId] [IndicatorName] [IndicatorValue]

そして、結果値は次のようになります。

1 1 'Indicator1' 'Value of Indicator 1 for entity 1'
2 1 'Indicator2' 'Value of Indicator 2 for entity 1'
3 1 'Indicator3' 'Value of Indicator 3 for entity 1'
4 2 'Indicator1' 'Value of Indicator 1 for entity 2'

などなど...。

これは意味があるのでしょうか?T-SQLでどこを見て、どうすればいいのか、何か提案はありますか?

どのように解決するのですか?

を使用することができます。 UNPIVOT 関数を使用して、列を行に変換することができます。

select id, entityId,
  indicatorname,
  indicatorvalue
from yourtable
unpivot
(
  indicatorvalue
  for indicatorname in (Indicator1, Indicator2, Indicator3)
) unpiv;

注意:ピボット解除する列のデータ型は同じでなければならないので、ピボット解除を適用する前にデータ型の変換が必要になる場合があります。

また CROSS APPLY をUNION ALLと組み合わせて、カラムを変換します。

select id, entityid,
  indicatorname,
  indicatorvalue
from yourtable
cross apply
(
  select 'Indicator1', Indicator1 union all
  select 'Indicator2', Indicator2 union all
  select 'Indicator3', Indicator3 union all
  select 'Indicator4', Indicator4 
) c (indicatorname, indicatorvalue);

SQL Server のバージョンによっては、VALUES 節で CROSS APPLY を使用することもできます。

select id, entityid,
  indicatorname,
  indicatorvalue
from yourtable
cross apply
(
  values
  ('Indicator1', Indicator1),
  ('Indicator2', Indicator2),
  ('Indicator3', Indicator3),
  ('Indicator4', Indicator4)
) c (indicatorname, indicatorvalue);

最後に、ピボット解除する列が 150 個あり、クエリ全体をハードコードしたくない場合は、動的 SQL を使用して SQL 文を生成することができます。

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

select @colsUnpivot 
  = stuff((select ','+quotename(C.column_name)
           from information_schema.columns as C
           where C.table_name = 'yourtable' and
                 C.column_name like 'Indicator%'
           for xml path('')), 1, 1, '')

set @query 
  = 'select id, entityId,
        indicatorname,
        indicatorvalue
     from yourtable
     unpivot
     (
        indicatorvalue
        for indicatorname in ('+ @colsunpivot +')
     ) u'

exec sp_executesql @query;