Sql server 如何编写具有多条记录的动态列透视查询?

Sql server 如何编写具有多条记录的动态列透视查询?,sql-server,excel,tsql,pivot,pivot-table,Sql Server,Excel,Tsql,Pivot,Pivot Table,EDIT2:我做了一个新的有用的例子,进入了下一步,但仍然没有关于如何做一些事情的线索。请结账 我有下表: CREATE TABLE [dbo].[MyTable] ( [ID] [int] IDENTITY(1,1) NOT NULL ,[Name] [nvarchar](50) NULL ,[Quantity] [int] NULL ,[Period] [nvarchar](10) NULL

EDIT2:我做了一个新的有用的例子,进入了下一步,但仍然没有关于如何做一些事情的线索。请结账

我有下表:

CREATE TABLE [dbo].[MyTable] (
             [ID] [int] IDENTITY(1,1) NOT NULL
            ,[Name] [nvarchar](50) NULL
            ,[Quantity] [int] NULL
            ,[Period] [nvarchar](10) NULL
            )

INSERT [dbo].[MyTable] VALUES
      ('foo', 1, 'Jan'),
      ('bar', 2, 'Jan'),
      ('foo', 1, 'Jan'),
      ('kin', 1, 'Jan'),
      ('blat', 5, 'Jan'),
      ('foo', 3, 'Feb'),
      ('bar', 1, 'Feb'),
      ('kin', 2, 'Feb'),
      ('blat',4, 'Feb'),
      ('foo', 1, 'Feb'),
      ('kin', 7, 'Feb'),
      ('blat', 1, 'Feb'),
      ('foo', 3, 'Mar'),
      ('bar', 1, 'Mar'),
      ('kin', 1, 'Mar'),
      ('blat', 1, 'Mar'),
      ('bar', 1, 'Mar'),
      ('kin', 2, 'Mar'),
      ('blat', 3, 'Mar')
我想通过在查询中使用枢轴来实现pic中的结果:

到目前为止,我的问题是:

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME(Period)
  FROM (SELECT Period FROM dbo.MyTable AS p
  GROUP BY Period) AS x;
SET @sql = N'
SELECT ' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT Name, Period, Quantity
   FROM dbo.MyTable AS p
) AS j
PIVOT
(
  SUM(Quantity) FOR Period IN ('
  + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
  + ')
) AS p;';
EXEC sp_executesql @sql;
给我下面的结果:

如何添加行名称(foo、bar、kin、blat)、列名、总和等

编辑3:如何“按”列和记录排序?

早上好,Tomo

现在,我们有了创建表和插入数据的查询,可以简单快速地帮助您:-)

请检查以下解决方案是否符合您的需要

select [Name],[Jan],[Feb],[Mar],[Jan]+[Feb]+[Mar] AS Grand_Total
from (
    SELECT [Name], [Quantity],[Period]
    FROM [MyTable]
) src
pivot
(
  SUM(Quantity)
  for Period in ([Jan],[Feb],[Mar])
) piv
GO
下一步是将其转换为动态PIVOT,一旦我们有了静态解决方案,这非常简单,如果您需要动态PIVOT。但首先确认静态PIVOT返回您需要的内容,并且您确实需要一个动态解决方案(可能这符合您的需要)

更新:使用汇总在底部添加“总计”

;With MyCTE as(
select [Name],[Jan],[Feb],[Mar],[Jan]+[Feb]+[Mar] AS Grand_Total
from (
    SELECT [Name], [Quantity],[Period]
    FROM [MyTable]
) src
pivot
(
  SUM(Quantity)
  for Period in ([Jan],[Feb],[Mar])
) piv
)
select ISNULL([Name],'Totoal') as Name ,SUM([Jan]) [Jan],SUM([Feb]) [Feb],SUM([Mar]) [Mar],SUM([Grand_Total]) [Grand_Total]
from MyCTE
GROUP BY ROLLUP ([Name])
GO
根据OP的要求添加动态Pivot版本

DECLARE 
    @ColumnsList1 AS NVARCHAR(MAX),
    @ColumnsList2 AS NVARCHAR(MAX),
    @ColumnsList3 AS NVARCHAR(MAX),
    @query AS NVARCHAR(MAX);

SET @ColumnsList1 = STUFF(
    (SELECT distinct ',' + QUOTENAME([Period]) FROM [MyTable] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')
PRINT @ColumnsList1
SET @ColumnsList2 = REPLACE (@ColumnsList1, ',','+')
PRINT @ColumnsList2
SET @ColumnsList3 = (
    SELECT distinct ',SUM(' + QUOTENAME([Period]) + ') as ' + QUOTENAME([Period])
    FROM [MyTable] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT @ColumnsList3

SET @query = '
;With MyCTE as(
select [Name],'+@ColumnsList1+','+@ColumnsList2+' AS Grand_Total
from (
    SELECT [Name], [Quantity],[Period]
    FROM [MyTable]
) src
pivot
(
  SUM(Quantity)
  for Period in ('+@ColumnsList1+')
) piv
)
select ISNULL([Name],''Totoal'') as Name '+@ColumnsList3+',SUM([Grand_Total]) [Grand_Total]
from MyCTE
GROUP BY ROLLUP ([Name])
'
execute(@query)
GO

这里的一些实际示例数据和预期结果会有所帮助。为什么要编写查询?如果要在excel中使用,请使用数据透视表。这是最简单的解决办法。事实上,我很困惑-您已经在示例中使用了透视表示例数据在图片中,预期结果在第一个中。因为它是整个过程的一部分,需要通过SQL实现自动化。请将excel中的结果与SQL中的结果进行比较。该图片不是示例数据,这是预期结果;图片对可消费数据没有帮助。我明白了,但为什么需要样本数据呢。我的目标是在查询中添加PartName行,就像它们在Excel中一样。相反,我有一个PartName行的总和。我确认它可以完成这项工作。没有底部的总计,我可以活下去。我没有注意到你要求底部的总计
:-)
。我会在晚餐回来后添加它,但我想说的是,你所有的要求都毫无意义。你应该在客户端而不是服务器端完成。将更多数据从服务器传递到客户端有什么意义?!?如果您使用远程服务器,则意味着您通过internet传递数据。。。这将减慢整个过程,并将导致服务器端的更多资源需要等待与客户端的连接完成
:-)
如果这符合您的需要(但我建议阅读我以前的评论),您可以检查并将其标记为答案。现在请看动态透视图。excel透视图是在excel中完成的几个小时流程的一部分。我的老板希望它在SQL中自动化,以缩短时间。这并不一定意味着我不同意你。