SQL Pivot Table from dynamic columns - sql

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)

Related

How to Un Pivot the Table With Date Headers in Sql

I have the following Temp table with Date Header How to UnPivot this Table
I need Like This type result
Here is the solution to your Problem:
DECLARE #colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsUnpivot
= stuff((select ','+quotename(C.name)
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('table')
for xml path('')), 1, 1, '')
set #query
= 'select sno,EmpId, Name, Date, Value
from table
unpivot
(
Date
FOR EmpId IN ('+ #colsunpivot +')
) u'
exec sp_executesql #query;
I used dynamic query since if you don't know how much columns are there in your table.
You can also use below static query :
SELECT sno, EmpId, Name, Date, Value
FROM
(SELECT *
FROM table) p
UNPIVOT
(Date FOR EmpId IN
(01-Mar-18,02-Mar-18,03-Mar-18,04-Mar-18,05-Mar-18)
)AS unpvt;
try the following script:
SELECT [s#no], [Emp#ID], [Name], [Date], [Shiftid]
FROM
(SELECT * FROM table_name) SRC
UNPIVOT
([Date] FOR [Emp#ID]
IN ([01-Mar-18], [02-Mar-18], [03-Mar-18], [04-Mar-18], [05-Mar-18])
) UNPVT;

Dynamic Query Restructuring for View

I have created a dynamic SQL query that I want to use as a view, however, the query is dependent on using 'DECLARE' statements. I have tried unsuccessfully to restructure it without the 'DECLARE' statements, but can't quite get it right. I am using SQL Server Express 2014 and would appreciate any and all help.
DECLARE #query nvarchar(MAX)
DECLARE #Name nvarchar(MAX)
select #Name = STUFF((SELECT distinct ',' + QUOTENAME(Name)
FROM [dbo].[ObjectView]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = ' SELECT * from
(
select *
from [dbo].[ObjectView]
)t
pivot (MAX(Value) for Name IN (' +#Name+ ')) AS PivotTable'
execute(#query)
You may have to play with the XML syntax. I'm pretty rusty.
create view viewname as
select * --< you really should call out the fields, here...
from(
select * --< ...and here.
from ObjectView
t
pivot( MAX( Value ) for Name in(
select distinct QUOTENAME( Name )
FROM ObjectView
FOR XML PATH )
) AS PivotTable

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

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;

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)

PIVOT for in many column headers using field [duplicate]

This question already has answers here:
Get ROWS as COLUMNS (SQL Server dynamic PIVOT query)
(2 answers)
Closed 9 years ago.
I have the following basic SQL statement which uses the PIVOT command.
SELECT *
FROM
(
--select statement that creates my dataset
) s
PIVOT (Max(incidentcount) for dept in ([dept1],[dept2])) p
This does what I expect it to do, it gives me a count of incidents per reason with depts as my columns. My problem is the departments that I am using for my columns go from 1-60.
Is there anyway I can tell the query to use the column Department to populate the PIVOT in part. Obviously I want to avoid manually typing each department.
EDIT
This is the sql that creates my dataset that I use in the pivot...
SELECT Details, Department , count(*) NoIncidents
FROM myincidentdb
Group by Details, Department
EDIT 2
You will want to use dynamic sql to PIVOT this, your code will be similar to this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(dept)
from yourtablewithDepartments
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *
from
(
<your query goes here>
) src
pivot
(
max(incidentcount)
for dept in (' + #cols + ')
) piv '
execute(#query)
If you post more details like table structure, etc then this can be refined to meet your needs.
Edit, based on your current query, it looks like you can use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsNull AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(department)
from myincidentdb
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Details, ' + #cols + '
from
(
select Details, Department
from myincidentdb
) x
pivot
(
count(Department)
for Department in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo