2

アプリケーションに SQL Server 2005 を使用しています。ストアド プロシージャに、C1 と C2 の 2 つの列を持つテーブルがあります。列 C1 の値が列になるように、このテーブルを転置したいと思います。転置前 (表 1):

C1  C2
M1  U1
M1  U2
M1  U3
M2  U4
M2  U5

転置後 (表 2):

M1  M2
U1  U4
U2  U5
U3  NULL

Table1 では、個別の値 (M1、M2) の数は異なる場合があります。そのため、Table2 の列は修正されていません。

同じことを達成するための解決策を提供してください。

4

3 に答える 3

2

このタイプのデータ変換PIVOTでは、SQL Server 2005+ で利用可能な関数を使用する必要があります。ピボット機能を適用するには 2 つの方法があります。

事前に値がわかっている場合は、クエリで値をハードコーディングできます。これに似ています:

select M1, M2
from
(
  select c1, c2,
    row_number() over(partition by c1 order by c1, c2) rn
  from yourtable
) src
pivot
(
  max(c2)
  for c1 in (M1, M2)
) piv

SQL Fiddle with Demoを参照してください。

ただし、列に転置する値の数が不明な場合は、動的 SQL を使用して実行時にクエリを作成できます。

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(C1) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ' + @cols + ' from 
             (
                select C1, C2,
                  row_number() over(partition by c1 order by c1, c2) rn
                from yourtable
            ) x
            pivot 
            (
                max(C2)
                for C1 in (' + @cols + ')
            ) p '

execute(@query)

SQL Fiddle with Demoを参照してください。

どちらも同じ結果になります。違いは、値が変更された場合に動的バージョンが柔軟であることです。

| M1 |     M2 |
---------------
| U1 |     U4 |
| U2 |     U5 |
| U3 | (null) |
于 2013-01-13T22:04:13.930 に答える
0

これはおそらく、動的 SQL があなたの味方であるケースです。ベーステーブルの名前が「Transpose」であると仮定します。

--Get a Unique List of values from C1 --> These will be our column headers
DECLARE @Unique TABLE (C1 VARCHAR(25), fUsed BIT DEFAULT 0);
INSERT INTO @Unique (C1) SELECT DISTINCT C1 FROM Transpose;

DECLARE @TransSQL NVARCHAR(4000);
DECLARE @ColID NVARCHAR(25);

SET @TransSQL = N'SELECT ' 

--Loop over unique C1 values and construct the select statement
SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0);
WHILE @@ROWCOUNT <> 0 AND @ColID IS NOT NULL
BEGIN
    SET @TransSQL = @TransSQL + 'CASE C1 WHEN ' + '''' + @ColID + '''' + ' THEN C2 ELSE NULL END AS ' + @ColID + ', '

    --Update flag in table so we don't use this field again
    UPDATE u SET fUsed = 1 FROM @Unique u WHERE C1 = @ColID;
    SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0);
END

--Remove Trailing comma and add FROM clause
DECLARE @SQL NVARCHAR(4000)
SET @SQL = LEFT(@TransSQL,LEN(@TransSQL) -1) + ' FROM Transpose'

--For debugging purposes
PRINT @SQL;

--Execute the dynamic sql
EXEC sp_executesql @SQL;

これは、結果をグループ化するためのキー フィールドではないため、質問で説明した正確なレイアウトにはなりません。代わりに、出力は次のようになります。

M1     M2      M3
U1     NULL    NULL
U2     NULL    NULL
U3     NULL    NULL
NULL   U4      NULL
NULL   U5      NULL
NULL   NULL    U6

ベース テーブルにキー フィールドがある場合、クエリをわずかに変更してキー フィールドごとに結果をグループ化すると、結果のデータに対する指定された目標に少し近づく可能性があります。

于 2011-12-08T14:39:57.793 に答える
0

これはあなたが望む正確な結果ではありませんが、これを試すことができます

;WITH TAB1 AS
( SELECT  [ResponsibleID] C1,[ActionID] C2,1 ORD
  FROM [TEST].[dbo].[yourtable]
  WHERE 1=1
  )


 SELECT 
    CASE WHEN M1=1 THEN ActionID ELSE NULL END M1,
    CASE WHEN M2=1 THEN ActionID ELSE NULL END M2 
 FROM TAB1
 PIVOT(AVG(ORD) FOR RESPONSIBLEID IN ([M1],[M2])) AS ABC
于 2011-12-13T03:43:52.683 に答える