使用SQL Server中的“Pivot”将行转换为列

23 浏览
0 Comments

使用SQL Server中的“Pivot”将行转换为列

我已经阅读了关于MS数据透视表的内容,但仍然无法正确地实现这个功能。\n我有一个临时表,我们假设第一列是店铺编号,第二列是周数,最后一列是某种类型的总数。此外,周数是动态的,店铺编号是静态的。\n我希望它以数据透视表的形式呈现,就像这样:\n店铺编号在左侧,周数在顶部。

0
0 Comments

问题的原因是需要将一个表的行转换为列,以实现更清晰的查询语法和方便的连接其他表的需求。使用子查询可以实现这个目的,但是在处理大量数据时会比较耗时。

解决方法是使用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

这种方法可以更高效地完成行列转换操作,并且可以方便地处理大量数据。

0
0 Comments

问题的出现原因:用户想要在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'将行转换为列的问题的出现原因和解决方法。

0
0 Comments

在使用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”的额外列。

可以使用我在上面提到的评论。

0