在SQL server中转换表
我正在为我的应用程序使用SQLServer2005。 我的存储过程中有一个表,它有两列,C1和C2。我想转置这个表,使列C1的值成为列。 转置前(表1): 转置后(表2): 在表1中,不同值(M1,M2)的数量可能不同。因此,表2中的列不是固定的在SQL server中转换表,sql,sql-server,pivot,transpose,Sql,Sql Server,Pivot,Transpose,我正在为我的应用程序使用SQLServer2005。 我的存储过程中有一个表,它有两列,C1和C2。我想转置这个表,使列C1的值成为列。 转置前(表1): 转置后(表2): 在表1中,不同值(M1,M2)的数量可能不同。因此,表2中的列不是固定的 请提供一个解决方案来实现同样的目标。这可能是动态sql是您的朋友的情况。假设基表的名称为“转置”: 如果您的基表有一个键字段,则可以稍微修改查询,以按键字段对结果进行分组,并可能更接近您对结果数据的指定目标。这不是您想要的确切结果,但您可以尝试一下 对
请提供一个解决方案来实现同样的目标。这可能是动态sql是您的朋友的情况。假设基表的名称为“转置”: 如果您的基表有一个键字段,则可以稍微修改查询,以按键字段对结果进行分组,并可能更接近您对结果数据的指定目标。这不是您想要的确切结果,但您可以尝试一下
对于这种类型的数据转换,您需要使用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) |
用动态SQL查询PIVOT;这个问题以前已经回答过好几次了。Hey的可能重复Hey的可能重复谢谢你的回答…有没有办法在SQL中只对coulmn进行排序,这样其他所有列就不会被排序了。在excel中,我们可以这样做。我不知道SQL Server。如果有任何方法可以做到这一点,请提供帮助。提前谢谢。这是一个很好的解决方案,但是你能详细说明一下在这种情况下,
row_number()over(按c1顺序划分,按c1,c2)rn
的作用吗?@JeremyS。使用字符串值时,聚合选项仅限于max
或min
。因此,如果不使用行编号
,您将只得到一行。带有分区的行编号
生成一个不同的值,该值在分组过程中保持值之间的分隔。请看,如果没有<代码> RoWixNo.<代码>,你只得到一行。感谢这个例子,我看到了,仍然不明白MSSQL是如何考虑把代码> RooSoxNo.<代码>作为一个不同的值,它不包含在GROUPBY子句中,因为没有,为什么MSSQL知道?@ JeleMy.PIVOT
正在执行聚合,而group by
未明确说明正在使用。我建议阅读MSDN上的。或者,如果您有特定问题,请发布新问题。:)您好,您的转置对我非常有用,但我不能在mysql服务器5.1上使用它。我在开始时遇到了一个关于“声明”的错误。我能做些什么来完成这次跑步?
M1 M2 M3
U1 NULL NULL
U2 NULL NULL
U3 NULL NULL
NULL U4 NULL
NULL U5 NULL
NULL NULL U6
;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
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
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) |