Using a Temp Table in a Dynamic Pivot - sql-server

I am trying to use a temp table inside of a dynamic pivot query. I have read that the procedure will not work because the temp table is outside of the scope even though it is a global table. This is strange to me because it works in sql fiddle but not in SQL Server 2012. How can I edit my query so that it gives me an output other than (xxx row(s) affected)?
Here is my query:
SELECT cc.CaseCaseId AS CaseId, cc.Label AS CaseName, rce.EcoDate, cc.OperatorName, cc.State, cc.County, ei.IROR, rce.NDCash
into ##Temp2
FROM PhdRpt.ReportCaseList_542 AS rcl INNER JOIN
CaseCases AS cc ON rcl.CaseCaseId = cc.CaseCaseId INNER JOIN
PhdRpt.RptCaseEco_542 AS rce ON rcl.ReportRunCaseId = rce.ReportRunCaseId INNER JOIN
PhdRpt.EcoIndicators_542 AS ei ON rcl.ReportRunCaseId = ei.ReportRunCaseId
DECLARE #colsPivot AS NVARCHAR(MAX),
#colsUnpivot as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(EcoDate)
from ##Temp2
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('##Temp2') and
C.name LIKE 'NDCash%'
for xml path('')), 1, 1, '')
set #query
= 'select *
from
(
select cc.CaseCaseId AS CaseId, cc.Label AS CaseName, rce.EcoDate, cc.OperatorName, cc.State, cc.County, ei.IROR, val, col
FROM ##Temp2
unpivot
(
val
for col in ('+ #colsunpivot +')
) u
) x1
pivot
(
max(val)
for EcoDate in ('+ #colspivot +')
) p'
exec(#query)
Drop table ##Temp2
Here is the table structure:
CaseId EcoDate NDCash
2 2003-01-01 26.6384943638238
2 2004-01-01 23.9534867373416
2 2005-01-01 25.9197356158675
2 2006-01-01 25.3280437702064
2 2007-01-01 24.9828609298022
2 2008-01-01 26.4019321789285
2 2009-01-01 26.6384943638238
2 2010-01-01 24.0660715481002
2 2011-01-01 26.6384943638238
2 2012-01-01 22.5718444448345
2 2013-01-01 26.6384943638238

Unless I am missing something, you don't need to use UNPIVOT for this and you don't need to use a temp table, just query the data directly. It looks like your current query is only unpivoting one column which is not needed. You use unpivot to convert multiple columns into multiple rows.
You should be able to use:
DECLARE #colsPivot 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,'')
set #query
= 'select *
from
(
SELECT cc.CaseCaseId AS CaseId,
cc.Label AS CaseName,
rce.EcoDate,
cc.OperatorName,
cc.State,
cc.County,
ei.IROR,
rce.NDCash
FROM PhdRpt.ReportCaseList_542 AS rcl
INNER JOIN CaseCases AS cc
ON rcl.CaseCaseId = cc.CaseCaseId
INNER JOIN PhdRpt.RptCaseEco_542 AS rce
ON rcl.ReportRunCaseId = rce.ReportRunCaseId
INNER JOIN PhdRpt.EcoIndicators_542 AS ei
ON rcl.ReportRunCaseId = ei.ReportRunCaseId
) x1
pivot
(
max(NDCash)
for EcoDate in ('+ #colspivot +')
) p'
exec(#query)

change the exec(#query) to sp_executeSQl #query.
exec(#query) will not execute in the current context, but where as the sp_executeSQL will execute with the current context that includes the temporary tables as well.

Related

Remove Null Value in Multiple Dynamic Pivot Result

I want to use dynamic multiple pivot for my table. I successfully to pivot the table but the problem is there are a lot of NULL values.
This is my current result
And this is what I have tried:
CREATE table #tempdata(
Name Varchar(100),
date date,
MeterSN Varchar(100),
Reading float,
Usage VARCHAR(20),
UsageValue float,
RecordedBy Varchar(100),
Remark Varchar(100)
)
INSERT INTO #tempdata
SELECT c.Name, a.date, b.MeterSN, a.Reading, c.Name + ' Usage' AS Usage,
Reading - LAG(reading) over(partition By currentMeterSNID order by a.date) as UsageValue,
a.RecordedBy, a.Remark
FROM INF_Facility_ElectricalRecord a
INNER JOIN INF_Facility_ElectricalMeter b ON b.id = a.currentMeterSNID
INNER JOIN INF_Facility_Location c ON c.id = b.LocationID
WHERE a.date BETWEEN '2019-03-19' AND '2019-03-20'
ORDER BY c.Name, a.date, b.MeterSN
DECLARE #cols AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(Name)
from #tempdata
group by Name
order by Name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #cols2 = STUFF((SELECT ',' + QUOTENAME(Usage)
from #tempdata
group by Usage
order by Usage
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT CONVERT(VARCHAR(10),date,120) AS Date,' + #cols + ','+ #cols2 + ', recordedby AS [Recorded By] , remark AS Remark from
(
select name,date, Reading, Usage, UsageValue, remark, RecordedBy
from #tempdata
) x
pivot
(
MAX(Reading)
for Name in (' + #cols + ')
) p
pivot
(
MAX(UsageValue)
for Usage in (' + #cols2 + ')
) p
ORDER by date '
execute(#query);
drop table #tempdata
Is there any solution for my problem?

Dynaimic query in sql and how to implement it in view

enter image description hereMy Query dynamically create a list of skills in a single row. However i can not use this query in view as there are declare variables present in the query .How can i modify it to use it in a view and still be dynamic
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(col + '_' + cast(seq as
varchar(2)))
from
(
select seq = row_number() over(partition by Skill.ID_Job
order by Skill.ID_Job)
from dbo.Job_Skill Skill
Where Skill.Min_Job = 1 and Skill.Ideal_Job = 1
) hr
cross apply
(
select 'Skill',1
) c (col, val)
order by val , seq
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ID_Job, ' + #cols + N'
from
(
select hr.ID_Job,
col = c.col + ''_'' + cast(seq as varchar(2)),
c.val
from
(
select Skill.ID_Job,
Skill.ID_SKL_Job,
Skill.Min_Job,
Skill.Ideal_Job,
seq = row_number() over(partition by Skill.ID_Job
order by Skill.ID_Job)
from dbo.Job_Skill Skill
Where Skill.Min_Job = 1 and Skill.Ideal_Job = 1
) hr
cross apply
(
select ''Skill'', ID_SKL_Job
) c (col, val)
) x
pivot
(
max(val)
for col in (' + #cols + N')
) p
order by ID_Job'
exec sp_executesql #query
enter image description here
Not sure what you're trying to do but SQL doesn't support dynamic views.
Maybe using FOR XML and returning the result XML via output parameter in your procedure would work.
Then you could join the XML and query it using XQuery. If you returned a XML like:
DECLARE #xml xml = CONVERT(xml,
'<jobs>
<job id="1">
<skill>s1</skill>
<skill>s2</skill>
</job>
<job id="2">
<skill>s3</skill>
</job>
</jobs>')
You could query for certain skills like:
SELECT
j.*
, T.jobs.query('skill') AS skill
FROM #xml.nodes('jobs/job') T(jobs)
INNER JOIN jobs j ON j.id = t.jobs.value('#id','int')
WHERE T.jobs.exist('skill[.="s1"]') = 1
p.s. from what I can tell, using XML would allow you to scratch dynamic sql, since you could group skills by job_id from the start, having one column as job_id, second one as resulting XML, implement it in a view or inline function and then you can join by the id and query the XML without using any programming.

SQl server Dynamic query

I have a table Connection
KEY Base_TBL Connected_table Base_tbl_colmn Connected_table_colmn
---- ------ ------------- ------------ ------------------
PRM Table1 Table2,Table3 colm1 Colm2,colm3
FRN Table4 table5 colm4 colm5
I need to generate a dynamic Query which should give an output something like this
select * from table1
INNER JOIN Table 2
ON table1.colm1 =table2.colm2
INNER JOIN Table3
on Table1.colm1=tabl3.colm3
number of tables in Connected_table can be anything and i have to join on the basis of that.
I have tried REPLACE Function within The dynamic query but not getting the desired result.
CREATE PROCEDURE [dbo].jointables
[Key] nvarchar(10)
AS
BEGIN
SET NOCOUNT ON
SET ROWCOUNT 0
DECLARE #sql as nvarchar(4000)
select #sql= 'select * from '+ Base_TBL + 'inner join ' +
Please guide me how to proceed further
CREATE FUNCTION [dbo].[FN_SPLIT](#Long_str varchar(max),#split_str varchar(100))
RETURNS #tmp TABLE(
ID inT IDENTITY PRIMARY KEY,
SPLIT varchar(max)
)
AS
BEGIN
DECLARE #sxml XML
SET #sxml='<root><node>'+REPLACE(#Long_str,#split_str,'</node><node>')+'</node></root>'
INSERT INTO #tmp([SPLIT])
SELECT b.value('.','varchar(max)') FROM #sxml.nodes('root/node') AS s(b)
RETURN
END
GO
DECLARE #sql as nvarchar(4000)
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
;WITH testdata AS
(
select 'PRM' AS [Key],'Table1' AS Base_TBL,'Table2,Table3' AS Connected_table,'colm1' AS Base_tbl_colmn,'Colm2,colm3' AS Connected_table_colmn
)
SELECT * INTO #temp FROM testdata
select #sql= 'select * from '+ Base_TBL +' ' +t.joinstring
FROM #temp
CROSS APPLY (
SELECT STUFF((
SELECT ' INNER JOIN '+ ft.[SPLIT] + ' ON ' + Base_TBL+'.'+Base_tbl_colmn +'='+ft.[SPLIT]+'.'+fc.[SPLIT]
FROM
dbo.FN_SPLIT(Connected_table,',') AS ft
INNER JOIN dbo.FN_SPLIT(Connected_table_colmn,',') AS fc ON fc.ID=ft.ID
FOR XML PATH('')),1,1,'') AS joinstring
) AS t
SELECT #sql
Below example just process one line
when process multiple lines, you can use another stuff function combine multiple lines
SELECT STUFF((
select ' select * from '+ Base_TBL +' ' +t.joinstring
FROM #temp
CROSS APPLY (
SELECT STUFF((
SELECT ' INNER JOIN '+ ft.[SPLIT] + ' ON ' + Base_TBL+'.'+Base_tbl_colmn +'='+ft.[SPLIT]+'.'+fc.[SPLIT]
FROM
dbo.FN_SPLIT(Connected_table,',') AS ft
INNER JOIN dbo.FN_SPLIT(Connected_table_colmn,',') AS fc ON fc.ID=ft.ID
FOR XML PATH('')),1,1,'') AS joinstring
) AS t FOR XML PATH('')
),1,1,'')

How do I unpivot/pivot dynamically while keeping original order of my columns?

I'm making an accounting report by performing a bunch of calculations on a table and transposing it by unpivoting/pivoting so it matches the format I want.
The problem is when I unpivot the columns into the rows the resulting output automatically sorts the rows by alphabetical order. I want to know if there's a way to stop the unpivot from doing that and transposing the exact order of the columns into the rows.
Here's my code for the dynamic pivot/unpivot:
ALTER PROCEDURE dbo.GenerateFormattedFFOReport
AS
BEGIN
SET NOCOUNT ON;
DECLARE #COLSUNPIVOT AS NVARCHAR(MAX),
#QUERY AS NVARCHAR(MAX),
#COLSPIVOT AS NVARCHAR(MAX),
#COLSUNPIVOTORDER AS NVARCHAR(MAX)
SELECT #COLSUNPIVOT = STUFF((SELECT ','+QUOTENAME(C.NAME)
FROM SYS.COLUMNS C WITH(NOLOCK)
WHERE C.OBJECT_ID = OBJECT_ID('GenerateFFOReportData') AND C.NAME <> 'Quarter'
FOR XML PATH('')), 1, 1, '')
SELECT #COLSUNPIVOTORDER = STUFF
SELECT #COLSPIVOT = STUFF((SELECT ',' + QUOTENAME([Quarter])
FROM GenerateFFOReportData T FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SELECT #COLSUNPIVOT
SET #QUERY
= 'SELECT HEADER, '+#COLSPIVOT+'
FROM
(
SELECT HEADER,[Quarter],VALUE FROM GenerateFFOReportData
UNPIVOT
(
VALUE FOR HEADER IN ('+#COLSUNPIVOT+')
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR [Quarter] IN ('+#COLSPIVOT+')
) PIV'
EXEC (#QUERY)
END
GO
Thanks for any help you can give.

T-SQL query on dynamic field with pivot

i have 3 table PhoneBook, DynamicField, PhoneBook_DynamicField_Rel
PhoneBook :
|---ID----|---Name----|
1 Reza
2 Ali
DynamicField :
|---ID----|--Caption--|
1 Job
2 Level
PhoneBook_DynamicField_Rel:
|---ID----|--PhoneBookID--|--DynamicFieldID--|---Value---|
1 1 1 Emp
2 1 2 1
3 2 1 SomeJob
i want execute query with this result :
|--PhoneBookID--|--Name--|--Job--|--Level--|
1 Reza Emp 1
2 Ali SomeJob NULL
Maybe something like this:
Test data:
CREATE TABLE #PhoneBook(ID INT,Name VARCHAR(100))
INSERT INTO #PhoneBook VALUES(1,'Reza'),(2,'Ali')
CREATE TABLE #DynamicField(ID INT,Caption VARCHAR(100))
INSERT INTO #DynamicField VALUES(1,'Job'),(2,'Level')
CREATE TABLE #PhoneBook_DynamicField_Rel(ID INT,PhoneBookID INT,
DynamicFieldID INT,Value VARCHAR(100))
INSERT INTO #PhoneBook_DynamicField_Rel
VALUES(1,1,1,'Emp'),(2,1,2,'1'),(3,2,1,'SomeJob')
Getting the colums
DECLARE #cols VARCHAR(MAX)
SELECT #cols=STUFF
(
(
SELECT
',' +QUOTENAME(tbl.Caption)
FROM
#DynamicField AS tbl
FOR XML PATH('')
)
,1,1,'')
Then the query like this:
DECLARE #query NVARCHAR(4000)=
N'SELECT
*
FROM
(
SELECT
*
FROM
(
SELECT
PhoneBook.ID,
PhoneBook.Name,
field.Caption,
rel.Value
FROM
#PhoneBook AS PhoneBook
JOIN #PhoneBook_DynamicField_Rel AS rel
ON PhoneBook.ID = rel.PhoneBookID
JOIN #DynamicField AS field
ON rel.DynamicFieldID=field.ID
) AS SourceTable
) AS p
PIVOT
(
MAX(Value) FOR Caption IN('+#cols+')
) AS pvt'
EXECUTE(#query)
Then in my case I will drop the temp tables:
DROP TABLE #PhoneBook
DROP TABLE #DynamicField
DROP TABLE #PhoneBook_DynamicField_Rel
What you need is dynamic pivot:
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(caption)
FROM DynamicField
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #q nvarchar(max)
set #q = '
select PhoneBookID, Name, ' + #collist + '
from (
select PhoneBookID, Name, Caption, Value
from (
select PhoneBookID, Name, Caption, Value
from PhoneBook pb
inner join PhoneBook_DynamicField_Rel pbdf on pb.ID = pbdf.PhoneBookID
inner join DynamicField df on df.ID = pbdf.DynamicFieldID
) as x
) as source
pivot (
max(Value)
for caption in (' + #collist + ')
) as pvt
'
exec (#q)

Resources