EDIT2: I made a new usable example, reached the next step, but still have no clue on how to do some stuff. Check, please.
I have the table below:
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')
And I want to achieve the result in the pic by using a PIVOT in a query:
My query so far:
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;
Gives me the result below:
How can I add row names (foo, bar, kin, blat), the column name Name, the SUMs etc.?
EDIT3: How to ‘ORDER BY’ the columns and the records?
Good day Tomo,
Now that we have the queries to create the table and insert the data, it is simple and fast to help you 🙂
Please check if the bellow solution fit your needs
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
Next step is to convert this into dynamic PIVOT which is very simple once we have the static solution, if you need dynamic PIVOT.But first confirm the static PIVOT returns what you need and that you actually need a dynamic solution (maybe this fit your needs as it is)
Update: add “Grand Total” at the bottom using 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
Adding Dynamic Pivot version as the OP asked for
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],'[email protected]+','[email protected]+' AS Grand_Total
from (
SELECT [Name], [Quantity],[Period]
FROM [MyTable]
) src
pivot
(
SUM(Quantity)
for Period in ('[email protected]+')
) piv
)
select ISNULL([Name],''Totoal'') as Name '[email protected]+',SUM([Grand_Total]) [Grand_Total]
from MyCTE
GROUP BY ROLLUP ([Name])
'
execute(@query)
GO

Tags: dynamic, sql-serversql