Как написать динамический столбец PIVOT-запрос с несколькими записями? - PullRequest
0 голосов
/ 05 февраля 2019

РЕДАКТИРОВАТЬ2: я сделал новый полезный пример, достиг следующего шага, но все еще не знаю, как сделать что-то.Проверьте, пожалуйста.

У меня есть таблица ниже:

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')

И я хочу добиться результата на рисунке, используя PIVOT в запросе:

enter image description here

Мой запрос пока:

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;

Дает мне результат ниже:

enter image description here

Как добавить имена строк (foo, bar, kin, blat), имя столбца Name, суммы и т. Д .?

EDIT3: как 'ORDER BY' столбцы и записи

1 Ответ

0 голосов
/ 05 февраля 2019

Добрый день, Томо,

Теперь, когда у нас есть запросы для создания таблицы и вставки данных, вам легко и быстро помочь :-)

Пожалуйста, проверьте нижерешение соответствует вашим потребностям

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 возвращает то, что вам нужно, ичто вам действительно нужно динамическое решение (может быть, оно соответствует вашим потребностям в том виде, в каком оно есть)

Обновление: добавьте «Общий итог» внизу, используя ROLLUP

;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

Добавление версии Dynamic 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
...