2

ジャンクションテーブルがあります:

id | warehouse | comp1 | comp2 | comp3 | comp4
----------------------------------------------
1  | w1        |   1   |  0    |  1    |  1    => String: 'col1,col3,col4'
2  | w2        |   1   |  1    |  0    |  1    => String: 'col1,col2,col4'
3  | w3        |   0   |  1    |  0    |  0    => String: 'col2'
  • 列の値が1の場合、列名の文字列を取得する方法は?

考えられる解決策 - ジャンクション テーブルを変更する

列名の操作を省略し、部分文字列またはマスクのみを操作します (like %comp1%例を使用):

id | warehouse| companies
-----------------------------------
1  | w1       | 'comp1,comp3,comp4'
2  | w2       | 'comp3'
3  | w3       | 'comp1,comp2,comp4'
4

2 に答える 2

4

必要なのは、基本的にunpivot除外された列名idwarehouse.

これを行う 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()ことも確認します。idwarehouse

于 2013-05-28T14:58:18.710 に答える
0

この場合のユースケース。

select case when column1=1 then '1' else '0' end as column1 from tableName
于 2013-05-28T06:18:55.307 に答える