2017-03-27 6 views
0

私はしばらくこのことに悩まされていました。このような答えをWebサイトで見つけられませんでした。既存の質問が存在する。 SQL Server 2012のでは、私は、主キーとしてIDを持つテーブルを持っている:私はテーブルの長さや列/カラム名 の量を知らない動的SQLを使用して列名を行として持つテーブルを再フォーマットする

ID  col1  col2 col3 .... 
--- ----  ----- ----- 
1  a  z  k 
2  g  b  p 
3  k  d  a 

が、私は得ることができるようにしたいです私は

SELECT COLUMN_NAME 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE 
TABLE_NAME = 'table' 

は私に私の列を取得し、私は 私に一時テーブルを作成するために、それを使用しようと試みたことを知っている

ID  ColName Value 
--- ----  ----- 
1  col1  a 
1  col2  z 
1  col3  k 
2  col1  g 
2  col2  b 
2  col3  p 
3  col1  k 
3  col2  d 
3  col3  a 
... 

:私のような何かを与えるテーブル私の望むフォーマットをテンポラリテーブルに書いてはいますが、テーブルの各行を調べ、各カラム名に対して必要な値を動的に取得して表示する方法がわかりません。私は二重カーソルでこれを達成することができましたが、それは痛みを伴いますが、私はSQLで比較的新しいので、これにどのようにアプローチすればよいか分かりません。どんな助けもありがとう!

編集

ので、非常に多くのLamakありがとうございます!私はさまざまなデータ型を持っていたし、varcharsにそれらをカバーして今私は概念が動作することを示す。しかし、私は4つの一般的なデータ型(varchar、float、int、datetime)を持っていますので、それぞれに4つの値フィールドがあります。その他の3つの空白。私はINFORMATION_SCHEMA.COLUMNSもdata_typesを提供しているので、単純なIF文に基づいて "STUFF"変数のデータ型を変換する構文が何か不思議でした。私は、列名にdata_typesをマッピングしようとしましたが、任意のタイプの条件文を持つとクエリが中断します。誰でも簡単な例を持っている場合、それは素晴らしいことだ:)

編集 実は、私は、各データは、むしろ型に私はちょうどでそれらすべてを行うよりも、4つの変数を作成する必要があると把握することができましたそれらの中の一つ。あなたの助けをありがとう!

+1

ありSO上の百例がありますが、ここでは、[ステップバイステップ偉大]です(http://sqlhints.com/2014/03/18/dynamic -pivot-in-sql-server /)を使用します。あなたは "Dynamic Pivot"を探しています – scsimon

+0

@scsimon百例がありますが、これは "dynamic ** unpivot **" – Lamak

答えて

1

コメントによると、ダイナミックピボットを使用する必要があります。データ型が異なる場合は、その後、あなたが最初の共通データ型にすべての列を変換する必要があります、今

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


SELECT @colsUnpivot = STUFF((SELECT ', ' + QUOTENAME(C.name) 
          FROM sys.columns as C 
          WHERE C.object_id = object_id('table') AND 
            C.name <> 'ID' 
          FOR XML PATH('')), 1, 1, ''); 

SET @query = ' 
SELECT ID, 
     ColName, 
     Value 
FROM 
(
    SELECT * 
    FROM dbo.table 
) x 
UNPIVOT 
(
    Value FOR ColName IN (' + @colsunpivot + ') 
) u 
'; 

EXEC(@query); 

:さておき、すべての列IDが同じデータ型を持っている場合

は、次のクエリを使用することができます。次の例では、私がNVARCHAR(1000)を使用しますが、あなたは正しいデータ型に変換する必要があります:あなたはDYNAMICを行く必要はありません

DECLARE @colsUnpivot1 AS NVARCHAR(MAX), 
     @colsUnpivot2 as NVARCHAR(MAX), 
     @query AS NVARCHAR(MAX); 


SELECT @colsUnpivot1 = STUFF((SELECT ', ' + QUOTENAME(C.name) 
          FROM sys.columns as C 
          WHERE C.object_id = object_id('table') AND 
            C.name <> 'ID' 
          FOR XML PATH('')), 1, 1, ''); 

SELECT @colsUnpivot2 = STUFF((SELECT ', CONVERT(NVARCHAR(1000),' + QUOTENAME(C.name) 
            + ') ' + QUOTENAME(C.name) 
          FROM sys.columns as C 
          WHERE C.object_id = object_id('table') AND 
            C.name <> 'ID' 
          FOR XML PATH('')), 1, 1, ''); 

SET @query = ' 
SELECT ID, 
     ColName, 
     Value 
FROM 
(
    SELECT ID, ' + @colsUnpivot2 + ' 
    FROM dbo.table 
) x 
UNPIVOT 
(
    Value FOR ColName IN ('+ @colsunpivot1 +') 
) u 
'; 

EXEC(@query); 
0

。 CROSS APPLYとXMLを使用した別のオプション。

UnPivotの方がパフォーマンスが優れていますが、このアプローチのパフォーマンスは非常に優れています。

このアプローチの追加の利点は、From @YourTable Aが任意のクエリ(テーブルに限定されない)である可能性があるということです。例えばFrom (-- Your Complex Query --) A

Declare @YourTable table (ID int,Col1 varchar(25),Col2 varchar(25),Col3 varchar(25)) 
Insert Into @YourTable values 
(1,'a','z','k') 
,(2,'g','b','p') 
,(3,'k','d','a') 


Select C.* 
From @YourTable A 
Cross Apply (Select XMLData=cast((Select A.* for XML Raw) as xml)) B 
Cross Apply (
       Select ID  = r.value('@ID','int') 
         ,Item = attr.value('local-name(.)','varchar(100)') 
         ,Value = attr.value('.','varchar(max)') 
       From B.XMLData.nodes('/row') as A(r) 
       Cross Apply A.r.nodes('./@*') AS B(attr) 
       Where attr.value('local-name(.)','varchar(100)') not in ('ID','OtherFieldsToExclude') 
      ) C 

戻り

ID Item Value 
1 Col1 a 
1 Col2 z 
1 Col3 k 
2 Col1 g 
2 Col2 b 
2 Col3 p 
3 Col1 k 
3 Col2 d 
3 Col3 a 
関連する問題