使用SQL Server中的“Pivot”将行转换为列
问题的原因是需要将一个表的行转换为列,以实现更清晰的查询语法和方便的连接其他表的需求。使用子查询可以实现这个目的,但是在处理大量数据时会比较耗时。
解决方法是使用SQL Server中的'Pivot'操作来实现行列转换。下面是一个示例代码:
SELECT StoreID, [1] AS Week1, [2] AS Week2, [3] AS Week3 FROM (SELECT StoreID, Week, ISNULL(SUM(xCount),0) AS xCount FROM StoreCountsByWeek GROUP BY StoreID, Week) AS SourceTable PIVOT ( SUM(xCount) FOR Week IN ([1], [2], [3]) ) AS PivotTable ORDER BY StoreID
这种方法可以更高效地完成行列转换操作,并且可以方便地处理大量数据。
问题的出现原因:用户想要在SQL Server中使用'Pivot'将行转换为列,以实现动态的周数。
解决方法:根据提供的示例,可以通过以下步骤解决问题:
1. 获取要进行Pivot操作的列的不同值。
2. 准备动态Pivot查询。
3. 执行动态Pivot查询。
具体做法如下所示:
DECLARE @PivotColumns AS NVARCHAR(MAX) DECLARE @PivotQuery AS NVARCHAR(MAX) -- 获取要进行Pivot操作的列的不同值 SELECT @PivotColumns = ISNULL(@PivotColumns + ',','') + QUOTENAME(Week) FROM (SELECT DISTINCT Week FROM #StoreSales) AS Weeks -- 准备动态Pivot查询 SET @PivotQuery = N'SELECT Store, ' + @PivotColumns + ' FROM #StoreSales PIVOT(SUM(xCount) FOR Week IN (' + @PivotColumns + ')) AS PVTTable' -- 执行动态Pivot查询 EXEC sp_executesql @PivotQuery
以上就是解决问题的方法,用户可以根据自己的需求进行相应的调整和使用。
此外,用户还提到了在dbfiddle上的一个示例,但该示例中未指定要进行Pivot操作的内容。并且该用户不确定在Postgres中是否可以进行此操作,因此他在SQL Server中提供了一个示例链接供参考。
以上就是关于如何在SQL Server中使用'Pivot'将行转换为列的问题的出现原因和解决方法。
在使用SQL Server 2005+时,可以使用PIVOT函数将数据从行转换为列。
如果周数是未知的,可能需要使用动态SQL,但最好先使用硬编码版本来查看正确的代码。
首先,这里有一些用于测试的快速表定义和数据:
创建表yt:
CREATE TABLE yt ( [Store] int, [Week] int, [xCount] int );
插入数据:
INSERT INTO yt ( [Store], [Week], [xCount] ) VALUES (102, 1, 96), (101, 1, 138), (105, 1, 37), (109, 1, 59), (101, 2, 282), (102, 2, 212), (105, 2, 78), (109, 2, 97), (105, 3, 60), (102, 3, 123), (101, 3, 220), (109, 3, 87);
如果你的值是已知的,你可以硬编码查询:
select * from ( select store, week, xCount from yt ) src pivot ( sum(xcount) for week in ([1], [2], [3]) ) piv;
动态版本的代码如下:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) select @cols = STUFF((SELECT ',' + QUOTENAME(Week) from yt group by Week order by Week FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = 'SELECT store,' + @cols + ' from ( select store, week, xCount from yt ) x pivot ( sum(xCount) for week in (' + @cols + ') ) p ' execute(@query);
以上两种方法都会得到相同的结果:
| STORE | 1 | 2 | 3 | --------------------------- | 101 | 138 | 282 | 220 | | 102 | 96 | 212 | 123 | | 105 | 37 | 78 | 60 | | 109 | 59 | 97 | 87 |
如何消除所有值为空的列?可以参考下面的回答。虽然没有直接尝试过,但概念是正确的。
如果在早期使用CTE构建了一个透视表cte3 AS (select ... )
,那么如果出现以下错误`Invalid object name 'cte3'.`,应该如何修复?
这很棒-很好。我以前从未使用过`STUFF(...)`函数(也没有使用过`XML PATH`)。为了让其他读者受益,这些代码的目的是将列名连接在一起并去掉前导逗号。请注意,我认为以下方法可能稍微简单一些:
select @cols = (SELECT DISTINCT QUOTENAME(Week) + ',' from yt order by 1 FOR XML PATH('')) set @cols = SUBSTRING(@cols, 1, LEN(@cols) - 1)
但是,即使是下面的回答也不能消除空值。
将`QUOTENAME(Week)`替换为`QUOTENAME(ISNULL(Week,'No Name'))`。并且将以下文本:`from select store, week, xCount from yt`替换为`select store, ISNULL(week,''No Name''), xCount from yt`。这将创建一个名为“No Name”的额外列。
可以使用我在上面提到的评论。