我正在为我的应用程序使用SQL Server 2005。 我的存储过程中有一个表,它有两列,C1和C2。我想转置这个表,使列C1的值成为列。 转置之前(表1):
C1 C2
M1 U1
M1 U2
M1 U3
M2 U4
M2 U5
转置后(表2):
M1 M2
U1 U4
U2 U5
U3 NULL
在表1中,不同值(M1,M2)的数量可以变化。因此,Table2中的列不能修复。
请提供实现相同目标的解决方案。
答案 0 :(得分:2)
对于此类数据转换,您将需要使用SQL Server 2005+中提供的PIVOT
函数。有两种方法可以应用 pivot 功能。
如果您提前知道这些值,则可以对查询中的值进行硬编码。与此类似:
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在运行时创建查询。
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)
两者都会给出相同的结果,不同之处在于动态版本是灵活的,如果值会改变:
| M1 | M2 |
---------------
| U1 | U4 |
| U2 | U5 |
| U3 | (null) |
答案 1 :(得分: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
如果您的基表有一个关键字段,则可以稍微修改查询以按键字段对结果进行分组,并且可能会更接近您对结果数据的既定目标。
答案 2 :(得分: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