2

I am using SQL Server 2005 for my application. I have a table in my stored procedure which has two columns, C1 and C2. I want to transpose this table such that the values of column C1 becomes the columns. Before transpose (Table 1):

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

After Transpose (Table 2):

M1  M2
U1  U4
U2  U5
U3  NULL

In Table1, the number of distinct values (M1, M2) may vary. So, the columns in Table2 are not fix.

Please provide a solution to achieve the same.

4

3 回答 3

2

对于这种类型的数据转换,您需要使用PIVOTSQL Server 2005+ 中提供的功能。有两种方法可以应用数据透视函数。

如果您提前知道这些值,则可以对查询中的值进行硬编码。与此类似:

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 是您朋友的情况。假设您的基表名称是“转置”:

--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 回答