必要なのは、基本的にunpivot
除外された列名id
とwarehouse
.
これを行う 1 つの方法は、列名の連結リストを作成するために使用するサブクエリでテーブル値コンストラクターを使用することです。for xml path('')
select T1.id,
T1.warehouse,
stuff((
select ','+T2.company
from (values(T1.comp1, 'comp1'),
(T1.comp2, 'comp2'),
(T1.comp3, 'comp3'),
(T1.comp4, 'comp4')) as T2(value, company)
where T2.value = 1
for xml path('')
), 1, 1, '') as comp
from YourTable as T1
SQL フィドル
新しい列を追加するときは、上記のクエリを変更する必要があります。動的な数の列で機能するクエリは、動的に生成する必要があります。sys.columnsを使用して列名を取得し、上記のクエリを動的に作成し、 execute を使用してクエリを実行できます。
declare @SQL nvarchar(max)
set @SQL = '
select T1.id,
T1.warehouse,
stuff((
select '',''+T2.company
from (values'+
stuff((
select ',(T1.'+name, ','''+name+''')'
from sys.columns
where object_name(object_id) = 'YourTable' and
name not in ('id', 'warehouse')
for xml path('')
), 1, 1, '') +
') as T2(value, company)
where T2.value = 1
for xml path('''')
), 1, 1, '''') as comp
from YourTable as T1'
exec (@SQL)
SQL フィドル
これには動的 SQL が必要だと言ったとき、私は完全に真実ではありませんでした。この場合、実際にはいくつかの xQuery を使用してこれを実現することができます。
select id,
warehouse,
stuff((
select ','+T3.N.value('local-name(.)', 'nvarchar(128)')
from T2.X.nodes('*[not(local-name() = ("id","warehouse"))]') as T3(N)
where T3.N.value('(./text())[1] cast as xs:boolean?', 'bit') = 1
for xml path('')
), 1, 1, '') as comp
from YourTable as T1
cross apply (
select T1.*
for xml path(''), type
) as T2(X)
SQL フィドル
コンマ区切りの列リストの作成は、 を使用した前のクエリと同じですfor xml path('')
。ここでクロス適用では、サブクエリで値と要素名をクエリするために使用される行ごとに構築された XML があります。要素名は列名に対応し、 を使用してアクセスしlocal-name(.)
ます。1 つの行の値は、式によってピボットされていません (実際の単語でさえあります) nodes()
。また、 andが列として返されないnodes()
ことも確認します。id
warehouse