Required pivot for below data structured - sql

i have data in below format.
ID question answer
1 who A
1 where B
1 when C
1 how D
i required output as below
id who where when how
1 A B C D

You can try this using dynamic pivot query.
create table #temp (ID int, question varchar(20), answer char(1))
insert into #temp values
(1, 'who', 'A'),
(1, 'where', 'B'),
(1, 'when', 'C'),
(1, 'how', 'D')
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.question)
FROM #temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Id, ' + #cols + ' from
(
select Id
,question
, answer
from #temp
) x
pivot
(
max(answer)
for question in (' + #cols + ')
) p '
execute(#query)
Live Demo

use conditional aggregation
select id,
max(case when question='who' then answer end) as "who",
max(case when question='where' then answer end) as "where",
max(case when question='when' then answer end) as "when",
max(case when question='how' then answer end) as "how"
from table_name
group by id

You may try this.
DECLARE #column AS VARCHAR(MAX), #query AS VARCHAR(MAX);
SET #column = STUFF((SELECT distinct ',' + QUOTENAME(t.question) FROM table t FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
set #query = 'SELECT Id, ' + #column + ' from
(
select Id, question, answer from table
) x
pivot
( max(answer) for question in (' + #column + ')
) p '
exec (#query)

Related

SQL Server Dynamic Pivoting - Not Usal Pivot With Count

I need to Pivot Questions With Their Answers.The Desired Output of the pivot Query is below and the table structure too.
I have Created the SQL fiddle Here Sql Fiddle. I saw many examples of count with pivot but couldn't find something similar to this.
You simply need some joins to get the base data and a dynamic pivot to show the result in the desired format.
try the following:
drop table if exists #temp
--base table with all details
select s.ID SurveyID, s.SubmittedBy, sq.Question, sa.Answer
into #temp
from #Survey s
join #SurveyMaster sm on sm.ID = s.SurveyMasterID
join #SurveyQuestion sq on sq.SurveyMasterID = s.SurveyMasterID
join #SurveyAnswers sa on sa.SurveyQuestionID = sq.ID and sa.SurveyID = s.ID
--dynamic pivot
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Question)
FROM #temp c
ORDER BY 1 DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT SurveyID, SubmittedBy, ' + #cols + ' from
(
select SurveyID, SubmittedBy, Question, Answer
from #temp
) x
pivot
(
max(Answer)
for Question in (' + #cols + ')
) p '
--execution
execute(#query)
Please find the db<>fiddle here.
declare #sqlstring as varchar(max) = '';
SELECT
#sqlstring = STUFF((
SELECT distinct
',' + '[' + isnull(sq.Question, '''') + ']'
from
#surveyanswers sa
join
#SurveyQuestion sq
on sq.ID = sa.SurveyQuestionID
join
#survey sv
on sv.SurveyMasterID = sq.SurveyMasterID FOR XML PATH('')), 1, 1, '')
select
sa.SurveyID,
sv.SubmittedBy,
sq.Question,
sa.Answer into ##temp
from
#surveyanswers sa
join
#SurveyQuestion sq
on sq.ID = sa.SurveyQuestionID
join
#survey sv
on sv.SurveyMasterID = sq.SurveyMasterID
set
#sqlstring = 'SELECT SurveyID,SubmittedBy,' + #sqlstring + ' FROM (select * from ##temp ) t ' + ' PIVOT ( ' + ' max(Answer) FOR Question IN (' + #sqlstring + ' ) ) AS pivot_table' execute(#sqlstring);
RESULT:

How To Set NULL is 0 in SQL Dynamic Pivot Query

I developed one dynamic pivot table, and I set ISNULL = 0.00.
The query is given below
SELECT DISTINCT hdr.EmpNo,hdr.FirstName AS Name,
ISNULL(TBL.shortname,'')AS shortname,
ISNULL(TBL.Amount,0.00) AS Amount,
TBL.Adtype INTO #Temp FROM tbl1 AS hdr
LEFT JOIN tbl2 TBL ON TBL.EmpNo = hdr.EmpNo
DECLARE #Ded AS NVARCHAR(MAX)
SET #Ded = STUFF((SELECT ', ISNULL( ' + QUOTENAME(c.shortname) + ', 0.00 )AS ' +
QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Query = 'SELECT CAST(ROW_NUMBER() OVER(ORDER BY EmpNo ASC) AS
VARCHAR(100)) AS [S.No],EmpNo,Name,' + #Ded +' FROM #Temp
PIVOT(SUM(Amount) FOR shortname IN (' + #Ded + ')) AS PVTTable'
EXEC sp_executesql #Query
But it displays the following error, and line 3 doesn't not have a "(".
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '('.
Any help to solve this problem would be appreciated.
Problem is with #der variable use in in clause.
you are setting column name with isnull and in in clause, it is not supported.
Please try below query.
;with tbl1 as
(
select 1 EmpNo,'Emp1' FirstName
union all
select 2 EmpNo,'Emp2' FirstName
),
tbl2 as
(
select 'EMP1' shortname,100 Amount, 2 Adtype,1 EmpNo
union all
select 'EMP2' shortname,100 Amount, 2 Adtype,2 EmpNo
)
SELECT DISTINCT hdr.EmpNo,hdr.FirstName AS Name,
ISNULL(TBL.shortname,'')AS shortname,
ISNULL(TBL.Amount,0.00) AS Amount,
TBL.Adtype INTO #Temp FROM tbl1 AS hdr
LEFT JOIN tbl2 TBL ON TBL.EmpNo = hdr.EmpNo
DECLARE #Ded AS NVARCHAR(MAX)='' ,#Query AS NVARCHAR(MAX)=''
DECLARE #Wer AS NVARCHAR(MAX)=''
SET #Ded = STUFF((SELECT ', ISNULL( ' + QUOTENAME(c.shortname) + ', 0.00 )AS ' +
QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Wer = STUFF((SELECT ', ' + QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Query = 'SELECT CAST(ROW_NUMBER() OVER(ORDER BY EmpNo ASC) AS
VARCHAR(100)) AS [S.No],EmpNo,Name,' + #Ded +' FROM #Temp
PIVOT(SUM(Amount) FOR shortname IN (' + #Wer + ')) AS PVTTable'
--print #Query
EXEC sp_executesql #Query

How to create a SQL Server Pivot query?

I want to create sql query result. I want to dynamically create because of inventory locations are one or more. (Example.. CTE)
Item_id Location Qty
--------------------------
1 a 1
2 b 2
3 c 3
3 a 1
2 c 2
1 b 3
Result is....
Item_id a_Location_Qty b_Location_Qty c_Location_Qty
-------------------------------------------------------
1 1 3 0
2 0 2 2
3 1 0 3
Please try below code
Create Table #Stack10072017040904(Item_id varchar(100),Location varchar(100),Qty int)
insert into #Stack10072017040904 select '1','a','1'
insert into #Stack10072017040904 select '2','b','2'
insert into #Stack10072017040904 select '3','c','3'
insert into #Stack10072017040904 select '3','a','1'
insert into #Stack10072017040904 select '2','c','2'
insert into #Stack10072017040904 select '1','b','3'
select Item_id,Isnull(a,0) a_Location_Qty
,isnull(b,0)b_Location_Qty
,isnull(c,0)c_Location_Qty
from #Stack10072017040904
pivot
(Sum(Qty) for Location in ([a],[b],c) )pvt
drop table #Stack10072017040904
Try this Dynamic Sql
Declare
#Sql nvarchar(max),
#dynamicCol nvarchar(max),
#dynamicCol2 nvarchar(max)
--Create columns Dynamically
SELECT #dynamicCol=STUFF((SELECT DISTINCT ', '+ QUOTENAME(Location )
From #Stack10072017040904 For XML PATH ('')),1,1,'')
SELECT #dynamicCol2=STUFF((SELECT DISTINCT ', '+ 'ISNULL ('+ QUOTENAME(Location )+ ','+'''0'''+')' +' AS '+Location+'_Location_Qty'
From #Stack10072017040904 For XML PATH ('')),1,1,'')
SET #Sql='
SELECT [Item_id] ,'+ #dynamicCol2 +' From
(
SELECT * From
#Stack10072017040904
)AS Src
PIVOT
(
MAX([Qty]) For [Location] IN ('+#dynamicCol+')
)
AS Pvt'
PRINT #Sql
EXEC(#Sql)
Result
Item_id a_Location_Qty b_Location_Qty c_Location_Qty
-------------------------------------------------------
1 1 3 0
2 0 2 2
3 1 0 3
Build columns dynamically and use a dynamic PIVOT:
Create Table #Test(Item_id varchar(100),Location varchar(100),Qty int)
insert into #Test values( '1','a','1')
insert into #Test values( '2','b','2')
insert into #Test values( '3','c','3')
insert into #Test values( '3','a','1')
insert into #Test values( '2','c','2')
insert into #Test values( '1','b','3')
DECLARE #cols1 AS NVARCHAR(MAX), #cols2 AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SET #cols1 = STUFF((SELECT distinct ', isnull(' + quotename(s.Location) + ', 0) as ' + quotename(s.Location)
FROM #Test s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #cols2 = STUFF((SELECT distinct ',' + quotename(s.Location)
FROM #Test s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Item_id, ' + #cols1 + ' from
(
select Item_id
, Location
, Qty
from #Test
) x
pivot
(
max(qty)
for Location in (' + #cols2 + ')
) p '
execute(#query)
drop table #Test

How to pivot rows into colums dynamically SQL Server

I have a request which returns something like this:
--------------------------
Tool | Week | Value
--------------------------
Test | 20 | 3
Sense | 20 | 2
Test | 19 | 2
And I want my input to look like this:
-------------------------
Tool | W20 | W19
-------------------------
Test | 3 | 2
Sense | 2 | null
Basically, for every week I need to have a new column. The number of week and of tools is dynamic.
I have tried many things but nothing worked. Anybody have a solution ?
Try this
CREATE table #tst (
Tool varchar(50), [Week] int, Value int
)
insert #tst
values
('Test', 20, 3),
('Sense', 20,2),
('Test', 19, 2)
Here is the Dynamic Query:
DECLARE #col nvarchar(max), #query NVARCHAR(MAX)
SELECT #col = STUFF((SELECT DISTINCT ',' + QUOTENAME('W' + CAST([Week] as VARCHAR))
from #tst
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = '
SELECT *
FROM (
SELECT Tool,
Value,
''W'' + CAST([Week] as VARCHAR) AS WeekNo
FROM #tst
) t
PIVOT
(
MAX(t.Value)
FOR WeekNo IN (' + #col + ')
) pv
ORDER by Tool'
EXEC (#query)
Result
Tool W20 W19
=================
Sense 2 NULL
Test 3 2
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
( Tool varchar(5), Week int, Value int)
;
INSERT INTO #temp
( Tool , Week , Value )
VALUES
('Test', 20, 3),
('Sense', 20, 2),
('Test', 19, 2)
;
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max),
#col NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ', ', '') + N'[' +'w'+ tbl.[Week] + ']'
FROM (
SELECT DISTINCT CAST([Week] AS VARCHAR)[Week]
FROM #temp
) AS tbl
SELECT #statement = 'SELECT *
FROM
(
SELECT
Tool , ''w''+ CAST(Week AS VARCHAR) week , Value
FROM
#Temp
) src
PIVOT(MAX(Value)for Week in (' + #columns + ')) as pvt
'
EXEC sp_executesql #statement = #statement
This is how I would do it ... If I understood your question correctly
if object_id('tempdb..#InputTool') is not null drop table #InputTool
create table #InputTool (Tool nvarchar(10), [20] int, [19] int)
insert into #InputTool (Tool, [20], [19])
values
('Test', 3, 2),
('Sense', 2, null)
declare #cols nvarchar(max)
select #cols = STUFF((SELECT ',' + QUOTENAME(name)
from tempdb.sys.columns
where object_id = object_id('tempdb..#InputTool')
and Column_id > 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #sqlquery nvarchar(max) =
'select Tool, Weeks, Value from (
select * from #InputTool
) as it
UNPIVOT
(
Value FOR Weeks IN (' + #cols + ')
) AS Weeks
order by Weeks desc'
execute (#sqlquery);
Give it a shot and let me know if it worked

SQL query unknown rows into columns

I asked this question and it was marked as a duplicate of How to pivot unknown number of columns & no aggregate in SQL Server?, but that answer doesn't help me.
I have a table of data that looks like this, with an unknown number of rows and values.
RecID Name Value
1 Color Red
2 Size Small
3 Weight 20lbs
4 Shape Square
I need a query that will return the data like this, building out a column for each row. I cannot hard code anything except the column headers 'Name' and 'Value'.
Color Size Weight Shape
Red Small 20lbs Square
Here is what I have so far that is partly working:
INSERT INTO #Table VALUES
(1,'Color' ,'Red'),
(2,'Size' ,'Small'),
(3,'Weight','20lbs'),
(4,'Shape' ,'Square')
;with mycte
as
(
SELECT rn,cols,val
FROM (SELECT row_number() over(order by Name) rn, Name, Value
FROM #Table) AS src1
UNPIVOT (val FOR cols
IN ( [Name], [Value])) AS unpvt
)
SELECT *
FROM (SELECT rn,cols,val
FROM mycte) AS src2 PIVOT
( Max(val) FOR rn IN ([1], [2], [3])) AS pvt
Which returns:
cols 1 2 3
Name Color Shape Size
Value Red Square Small
Two problems with this that I can't seem to resolve.
I don't need the column headers and the first column that has cols, Name, Value in it.
Can't figure out how to have it build a column for each row without specifying the [x] identifiers.
Any guidance would be great I've been stuck on this a while now.
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(name)
FROM #t -- your table here
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #q nvarchar(max)
set #q = '
select *
from (
select rn, name, Value
from (
select *, row_number() over (partition by name order by RecID desc) as rn
from #t -- your table here
) as x
) as source
pivot (
max(Value)
for name in (' + #collist + ')
) as pvt
'
exec (#q)
Until now, I have reached to following code, hope it helps you,
Current outpu comes as
Color Shape Size Weight
Red NULL NULL NULL
NULL NULL Small NULL
NULL NULL NULL 20lbs
NULL Square NULL NULL
Create table DyTable
(
tid int,
Name varchar(20),
Value varchar(20)
)
INSERT INTO DyTable VALUES
(1,'Color' ,'Red'),
(2,'Size' ,'Small'),
(3,'Weight','20lbs'),
(4,'Shape' ,'Square')
DECLARE #Cols NVARCHAR(MAX);
DECLARE #Cols1 NVARCHAR(MAX);
SELECT #Cols = STUFF((
SELECT DISTINCT ', ' + QUOTENAME(Name)
FROM DyTable
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
,#Cols1 = STUFF((
SELECT DISTINCT ', max(' + QUOTENAME(Name) + ') as ' + Name
FROM DyTable
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
DECLARE #Sql NVARCHAR(MAX)
Select #Cols
SET #Sql = 'Select '+ #Cols1 +'
from (SELECT ' + #Cols + '
FROM DyTable t
PIVOT (MAX(Value)
FOR Name
IN (' + #Cols + ')
)P)a'
EXECUTE sp_executesql #Sql