Need SQL pivot assistance as I do not have an aggregate column - sql

I have the following view I created that looks like this table.
Create Table #Temptable(
[Week number] int,
[Did Not meet minimum] int,
[Met minimum] int,
[exceeded minimum] int);
insert into #Temptable([Week number],[Did Not meet minimum],[Met minimum],[exceeded minimum])
values
(3,161,4,18),
(4,165,1,24),
(5,166,0,10)
I would like the output to be three lines so that I can create a trending report by week. I can populate a temp table to get the desired result but I would like to see if there is a better solution.
Label, week3, week4, week5
Did not meet minimum, 161, 165, 166
Met minimum, 4, 1, 0
Exceeded minimum, 18, 24, 10
If this is not possible from this data set I also have the source line item detail the view was created from. that dataset looks like this
techname,machinename,installdate,weeknumber
I made 3 scalar functions that aggregate by techname and week number so that I can get the Did not meet, Met, and exceeded install counts for each week.
Thank you in advance.
After getting the response from StuartLC I began to craft my own dynamic version I was close but as I was posting a response another kind person posted a working version. For everyone's benefit here is the sample code I put together it however is not working. If I copy the error text and just select the outputted query it does work properly.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[week number])
FROM SummarisedWeeklysums c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Criteria, '+ #Cols +' FROM
(
SELECT
*
FROM
SummarisedWeeklysums
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] IN ('+#Cols+')
)pvt'
execute #query

This is quite similar to my answer here - basically you are looking for a full transpose. This can be done with an unpivot, followed by a pivot:
SELECT Criteria, [3] as Week3, [4] AS Week4, [5] AS Week5
FROM
(
SELECT
*
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] IN ([3],[4],[5])
)pvt;
Fiddle here
Also, if you need to do this for a bunch of unknown weeks (or criteria, I guess), you can look at the answer here which uses dynamic sql to build up the columns and execute the pivot.

The is based on StuartLC answer and link (credit to you) with scalability if extra weeks are added in the future:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME('Week'+cast([Week Number] as varchar))
FROM #Temptable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
select #query =
'SELECT *
FROM
(
SELECT
''Week''+cast([Week number] as varchar) as [Week number] , CriteriaCount , Criteria
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] in (' + #cols + ')
)pvt ;';
execute(#query);
Below is the same code, with the results moved into a temp table (as requested by user3275636) and then displayed:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME('Week'+cast([Week Number] as varchar))
FROM #Temptable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
select #query =
'select * into ##temp1 from (SELECT *
FROM
(
SELECT
''Week''+cast([Week number] as varchar) as [Week number] , CriteriaCount , Criteria
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] in (' + #cols + ')
)pvt ) as combi;';
execute(#query);
select * from ##temp1;

Related

SQL Pivot Table from dynamic columns

I wrote this query to generate pivot table :
SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN (select ItemName_AR from WH_Items)
)AS pvt
but it cuases the following error in
Incorrect syntax near the keyword 'select'.
at this statment
FOR [ItemName] IN (select ItemName_AR from WH_Items)
Unfortunately, you may not use a select statement to provide the variety of values (unpivoted form)=columns(pivoted form). You may either use
IN ([value1],[value2]) etc
or consider a dynamic solution, here's a link:
SQL Server Dynamic Pivot Column Names
You cannot create Dynamic SQL PIVOT like that. You may try something like this...
DECLARE #cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ',' + Quotename(ItemName_AR)
FROM WH_Items
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE #query AS NVARCHAR(max) = 'SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN ('+ #cols +')
)AS pvt';
EXECUTE(#query)

Dynamic pivot - doesnt read the '+' sign

Hi I am trying to run the below code, but getting the error below. telling me that the issue is due to ' + #Cols + ', however this code is referenced from the forums. Any help would be greatly appreciated. Thanks
Error
Msg 102, Level 15, State 1, Line 27
Incorrect syntax near ' + #Cols + '.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(year)
FROM [Reporting].[dbo].[FX_Table]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT *
FROM
(
SELECT
[from],
[Year],
[FX]
FROM [Reporting].[dbo].[FX_Table] WHERE [To] = 'Euro'
GROUP BY
[from],
[Year],
[FX]
) AS S
PIVOT
(
SUM(FX)
FOR [year] IN ' + #Cols + '
)
AS PVT
How about this?
SELECT *
FROM (
SELECT [from],
[Year],
[FX]
FROM [Reporting].[dbo].[FX_Table]
WHERE [To] = 'Euro'
GROUP BY [from],
[Year],
[FX]
) AS S
PIVOT(SUM(FX) FOR [year] IN (
SELECT DISTINCT year
FROM [Reporting].[dbo].[FX_Table]
)) AS PVT
You don't have to create a variable where you will store all your values and then try to use IN to go over those values and filter them.
Also, if you create a NVARCHAR variable to hold all your years, then you will have to split all those values, by comma, to use them with IN (which would make your declaration of variable #Cols useless).
What you will have in your #Cols variable, the way you create it now, is something like below (ONE record which is the list of years):
But for your IN clause to work, you would need multiple records, each year a new record, like below:
I hope this solves your problem.

Dynamic pivot table with multiple columns in sql server

I am trying to pivot table DYNAMICALLY but couldn't get the desired result.
Here is the code to create a table
create table Report
(
deck char(3),
Jib_in float,
rev int,
rev_insight int,
jib_out float,
creation int
)
insert into Report values
('A_1',0.345,0,0,1.23,20140212),
('B_2',0.456,0,4,2.34,20140215),
('C_3',0.554,0,6,0.45,20140217),
('D_4',0.231,0,8,7.98,20140222),
('E_5',0.453,0,0,5.67,20140219),
('F_6',0.344,0,3,7.23,20140223)'
Code written so far.... this pivots the column deck and jib_in into rows but thats it only TWO ROWS i.e the one i put inside aggregate function under PIVOT function and one i put inside QUOTENAME()
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(deck)
FROM (SELECT p.deck FROM dbo.report AS p
GROUP BY p.deck) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.deck, p.jib_in
FROM dbo.report AS p
) AS j
PIVOT
(
SUM(jib_in) FOR deck IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
I need all the columns to be pivoted and show on the pivoted table. any help would be appreciated. I am very new at dynamic pivot. I tried so many ways to add other columns but no avail!!
I know there are other ways please feel free to mention if there is any other way to get this right.
Please use this (If you are getting Collation issue, please change all the 3 INT datatypes):
STATIC code:
SELECT HEADER, [A_1],[B_2],[C_3],[D_4],[E_5],[F_6]
FROM
(SELECT DECK,HEADER, VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ([JIB_IN],[REV],[REV_INSIGHT],[JIB_OUT],[CREATION])
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ([A_1],[B_2],[C_3],[D_4],[E_5],[F_6])
) PIV
Using Dynamic SQL:
DECLARE #COLSUNPIVOT AS NVARCHAR(MAX),
#QUERY AS NVARCHAR(MAX),
#COLSPIVOT AS NVARCHAR(MAX)
SELECT #COLSUNPIVOT = STUFF((SELECT ','+QUOTENAME(C.NAME)
FROM SYS.COLUMNS AS C
WHERE C.OBJECT_ID = OBJECT_ID('REPORT') AND C.NAME <> 'DECK'
FOR XML PATH('')), 1, 1, '')
SELECT #COLSPIVOT = STUFF((SELECT ',' + QUOTENAME(DECK)
FROM REPORT T FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SET #QUERY
= 'SELECT HEADER, '+#COLSPIVOT+'
FROM
(
SELECT DECK,HEADER,VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ('+#COLSUNPIVOT+')
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ('+#COLSPIVOT+')
) PIV'
EXEC(#QUERY)

sql table row - column conversion

I have following table:
How to convert the above table into below structure? I tried using pivot table but couldn't get it to work.
You need to have to look up SQL PIVOT.
Check this fiddle
And the code:
SELECT *
FROM
(
SELECT Prodname,
pcode,
Biiledamt
FROM Product
) p
PIVOT
(
SUM (Biiledamt)
FOR Prodname IN ([Prod1],[Prod2],[Prod3],[Prod4])
) AS pvt
If you do not know beforehand the columns then you can check this fiddle which dynamically generates the columns to use.
The code for that is:
DECLARE #cols AS VARCHAR(MAX),
#query AS VARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',[' + Prodname +']'
FROM Product c
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1,1,'')
SET #query =
' SELECT *
FROM
(
SELECT Prodname,
pcode,
Biiledamt
FROM Product
) p
PIVOT
(
SUM (Biiledamt)
FOR Prodname IN (' + #cols + ')
) AS pvt
'
EXEC(#query)

TSQL - using IN with PIVOT

Quick question that's bugging me.
When using PIVOT in T-SQL, can the 'FOR..IN' portion reference a table rather than a defined list of values?
Example, instead of something like:-
PIVOT (Count(widgets) For Team IN ([Dave],[Peter],[John]....etc))
Could you do something like:-
PIVOT (Count(widgets) for Team IN (SELECT TeamLeader FROM Teams))
I can find no reference to confirm whether or not this is possible.
No, this is not possible.
The PIVOT operator syntax dictates that these values is entered as a list:
...
IN ( [first pivoted column],
[second pivoted column],
...
...
[last pivoted column])
But you can do this dynamically, something like:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(Teamleader)
FROM Teams
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = ' SELECT ' + #cols +
' FROM AnotherTable a
PIVOT
(
Count(widgets) For Team IN (' + #cols + ')' +
') p';
execute(#query);