Inserting dynamic pivot result into an existing table without knowing table definition - sql

I have a dynamic pivot table that produces an unknown number of columns until runtime. I am trying to clear the data out of an existing table and insert the results of my query into it. The problem that I am having is that I do not know what the table definition will be ahead of time because it is dynamic.
Here is the error I am getting:
Msg 213, Level 16, State 7, Line 1
Column name or number of supplied values does not match table definition.
The pivoted column is a date column which could have 1 date or 1000+ dates.
How can I create a table definition that will match the data that I am trying to insert?
Here is my query:
DECLARE #colsPivot AS NVARCHAR(MAX),
#colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsPivot = STUFF((SELECT ',' + QUOTENAME(rce.EcoDate)
from PhdRpt.RptCaseEco_542 AS rce
group by rce.EcoDate
order by rce.EcoDate
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #colsUnpivot = stuff((SELECT ','+quotename(C.name)
FROM sys.columns AS C
WHERE C.object_id = object_id('PhdRpt.RptCaseEco_542') AND
C.name in ('NDCash', 'DCash')--LIKE '%Cash' or C.Name like 'NetGas'
FOR xml path('')), 1, 1, '')
set #query
= 'select *
--into ##hello
from
(
SELECT
ReportRunCaseId,
col,
EcoDate,
val
FROM PhdRpt.RptCaseEco_542
unpivot
(
val
for col in ('+ #colsunpivot +')
) u
) x1
pivot
(
max(val)
for EcoDate in ('+ #colspivot +')
) p'
truncate table dbo.Table1
insert into dbo.Table1
exec(#query)

I would DROP original table and just create new one on the fly using SELECT INTO clause.
by using SELECT INTO you do not need to create table before hand or worry what type and how many columns it will have. SQL Server will just create it for you.
Note: this only works when table does not exists.
Full documentation on INTO Clause http://technet.microsoft.com/en-us/library/ms188029.aspx
as another alternative you can always SELECT INTO #temp table that you can drop or use it to model your other table but I think this is extra work that you do not want to do.

You can do something like this:
DROP TABLE dbo.Table1
DECLARE #colsPivot AS NVARCHAR(MAX),
#colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsPivot = STUFF((SELECT ',' + QUOTENAME(rce.EcoDate)
from PhdRpt.RptCaseEco_542 AS rce
group by rce.EcoDate
order by rce.EcoDate
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #colsUnpivot = stuff((SELECT ','+quotename(C.name)
FROM sys.columns AS C
WHERE C.object_id = object_id('PhdRpt.RptCaseEco_542') AND
C.name in ('NDCash', 'DCash')--LIKE '%Cash' or C.Name like 'NetGas'
FOR xml path('')), 1, 1, '')
set #query
= 'select *
into dbo.Table1
from
(
SELECT
ReportRunCaseId,
col,
EcoDate,
val
FROM PhdRpt.RptCaseEco_542
unpivot
(
val
for col in ('+ #colsunpivot +')
) u
) x1
pivot
(
max(val)
for EcoDate in ('+ #colspivot +')
) p'
exec(#query)

Related

The type of column "Date" conflicts with the type of other columns specified in the UNPIVOT list

I have the following code to do Pivot and Unpivot on a set of columns:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsUnpivot AS NVARCHAR(MAX)
select #colsUnpivot = stuff((select ','+quotename(C.name)
from tempdb.sys.columns as C
where C.object_id = object_id('tempdb..#TmpTable')
for xml path('')), 1, 1, '')
SET #cols = STUFF((SELECT ',' + QUOTENAME(a.Date)
FROM
(Select top 10000 date from
#TmpTable
order by date) a
group by a.Date
order by a.Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name, ' + #cols + ' from
(
select Date,name,value
from #TmpTable
unpivot
(
value for name in ('+#colsUnpivot+')
) unpiv
) x
pivot
(
sum(value)
for date in (' + #cols + ')
) p '
exec(#query)
But, I keep getting these errors which I can't figure out why:
The type of column "Date" conflicts with the type of other columns specified in the UNPIVOT list.
Invalid column name 'Date'
The type of Date column in the temp table is datetime.
This post was very helpful to explain the issue. Basically, I had to convert the values to decimal for all the columns in the inner select statement of the unpivot section:
Error : The type of column "DOB" conflicts with the type of other columns specified in the UNPIVOT list

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;

Combine two pivot tables SQL Server

I am trying to cross join two pivot tables.
--First Pivot table query gets columns of drug_names and produces the row value
--of the drug_id.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
DECLARE #cols AS NVARCHAR(MAX),#scols as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols + N')
) p'
exec sp_executesql #query;
Now I just need to know how to combine these two pivot tables as one table... they don't have a common field and don't need one.
Can anybody help me with this one?
Thank you
You can execute two separate dynamic SQL statements into two global temp tables and then combine the result, like this:
IF object_id('tempdb..##tmpResult1') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult1
END
IF object_id('tempdb..##tmpResult2') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult2
END
DECLARE #cols AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' INTO ##tmpResult1 from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
Select #cols2 = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = N'SELECT ' + #cols2 + N' INTO ##tmpResult2 from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols2 + N')
) p'
exec sp_executesql #query2;
SELECT * FROM ##tmpResult1 t1
INNER JOIN ##tmpResult2 t2 ON t1.ordernumber = t2.ordernumber
This is also a way to address this error when doing a large PIVOT query: Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.

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 Removing a filter from an unpivot table

I have this unpivot table and I wish to remove the filter that is applied to it.
DECLARE #colsPivot AS NVARCHAR(MAX),
#colsUnpivot as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(year(EcoDate))
from PhdRpt.RptCaseEco
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('PhdRpt.RptCaseEco')
and C.name Like 'Net%'
for xml path('')), 1, 1, '')
set #query
= 'select *
from
(
select reportruncaseid, year(Ecodate) as EcoYear, val, col
from phdrpt.rptcaseeco
unpivot
(
val
for col in ('+ #colsUnpivot +')
) u
) x1
pivot
(
max(val)
for ecoyear in ('+ #colspivot +')
) p ORDER BY reportruncaseid'
exec(#query)
This table worked before because all the columns had a prefix of "Net" but now there are other columns that are being filtered out because they do not begin with "Net". I tried to remove --- and C.name Like 'Net%' --- but I keep getting these errors:
Msg 8167, Level 16, State 1, Line 10
The type of column "EcoDate" conflicts with the type of other columns specified in the UNPIVOT list.
Msg 207, Level 16, State 1, Line 4
Invalid column name 'reportruncaseid'.
Msg 207, Level 16, State 1, Line 4
Invalid column name 'Ecodate'.
Here is what the table looks like
The filter to get the list of columns to UNPIVOT can be removed but if there are columns that you do not want to UNPIVOT then you will need to exclude them:
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('PhdRpt.RptCaseEco')
and C.name not in ('reportruncaseid', 'Ecodate')
for xml path('')), 1, 1, '')
This will return all of the columns to unpivot, except reportruncaseid and Ecodate (or other columns you do not want unpivoted). So the full query will be:
DECLARE #colsPivot AS NVARCHAR(MAX),
#colsUnpivot as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(year(EcoDate))
from PhdRpt.RptCaseEco
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('PhdRpt.RptCaseEco')
and C.name not in ('reportruncaseid', 'Ecodate')
for xml path('')), 1, 1, '')
set #query
= 'select *
from
(
select reportruncaseid, year(Ecodate) as EcoYear, val, col
from phdrpt.rptcaseeco
unpivot
(
val
for col in ('+ #colsUnpivot +')
) u
) x1
pivot
(
max(val)
for ecoyear in ('+ #colspivot +')
) p ORDER BY reportruncaseid'
exec(#query);
Also if you have columns that are different datatypes, then you will have to cast them to the same datatype prior to applying the unpivot.