Remove Null Value in Multiple Dynamic Pivot Result - sql-server

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?

Related

The column 'JUN-2015' was specified multiple times for 'P'

I have created a dynamic pivot and my table has two same dates with diff values ..
i m facing an error when try the pivot
Error : the column 'JUN-2015' was specified multiple times for 'P'
...........................................................
CREATE TABLE #REVENUE
(
ID INT PRIMARY KEY IDENTITY(1,1) NOT NULL,
[MONTH] VARCHAR(8) NOT NULL,
SALES DECIMAL(8,2) NOT NULL
)
INSERT INTO #REVENUE
([MONTH],SALES)
VALUES
('JAN-2015', 200000.16),
('FEB-2015', 220000.17),
('MAR-2015', 227000.55),
('APR-2015', 247032.75),
('MAY-2015', 287652.75),
('JUN-2015', 265756.75),
('JUN-2015', 265756.75)
DECLARE #cols AS NVARCHAR(MAX) ,
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME([MONTH])
FROM #REVENUE
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #query =
'SELECT * FROM
(SELECT
[MONTH],
SALES
FROM #REVENUE)X
PIVOT
(
AVG(SALES)
for [MONTH] in (' + #cols + ')
) P'
EXEC SP_EXECUTESQL #query
If you select #cols you'll see the issue
Please use DISTINCT to avoid the situation:
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME([MONTH])
FROM #REVENUE
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')

Copy oldtable to newTable base on pivot query result?

I have a pivot query from pivoted table*(a dynamic columns)*, my problem is I want to copy/clone the pivot result into new_table. Which is I don't know how to do it,
Query:
DECLARE #cols NVARCHAR(MAX), #query NVARCHAR(MAX);
SET #cols = STUFF((SELECT DISTINCT','+QUOTENAME(c.ReportedDate)
FROM dbo.Activity c FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '');
SELECT #query = 'SELECT * FROM (SELECT b.Description, CONVERT(VARCHAR(10), reportedDate, 120) as reportedDate,Status
FROM Activity left join ActivityType b on b.activityTypeId = Activity.ActivityTypeId )
AS t PIVOT ( COUNT(reportedDate) FOR reportedDate IN( ' + #cols + ' )' + ') AS p ;'
EXECUTE (#query);
How to achieve my expectations to get the same result from pivotTable to new_table with the same data result?
You can use a table (or a global temporary table) to store data via select into, so you will able to have access on it.
DECLARE #cols NVARCHAR(MAX), #query NVARCHAR(MAX);
SET #cols = STUFF((SELECT DISTINCT','+QUOTENAME(c.ReportedDate)
FROM dbo.Activity c FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '');
SELECT #query = 'SELECT * into ##results FROM (SELECT b.Description, CONVERT(VARCHAR(10), reportedDate, 120) as reportedDate,Status
FROM Activity left join ActivityType b on b.activityTypeId = Activity.ActivityTypeId )
AS t PIVOT ( COUNT(reportedDate) FOR reportedDate IN( ' + #cols + ' )' + ') AS p ;'
EXECUTE (#query);
SELECT * FROM ##results

How Do I Join A SQL Pivot Query That Uses Delare Statements to a Normal SQL Query

Sorry if this isn't the best way to ask this but I am stuck at this point, I have tried researching but to no avail, trying to join these two queries:
SELECT [id]
,[title]
,[desc]
FROM [localTest].[dbo].[main];
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME([Year]) from [localTest].[dbo].[Years] FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT [ID], ' + #cols + ' from (select [ID], [Year], [Amount] FROM [localTest].[dbo].[Years] ) x pivot (min([Amount]) for [Year] in (' + #cols + ')) p '
execute(#query);
Looking for the final result here:
enter image description here
I figured it out, here is my solution:
DECLARE #cols AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' + QUOTENAME([Year]) FROM [localTest].[dbo].[Years] FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'');
DECLARE #Sql VARCHAR(max);
SELECT #Sql = 'SELECT * FROM [localTest].[dbo].[main] a join (
SELECT * FROM (
SELECT [ID] id, [Year], [Amount]
FROM [localTest].[dbo].[Years]
) x pivot (
min([Amount])
for [Year] IN ('+#cols+')
) p ) as b on a.[ID] = b.id';
EXECUTE(#Sql);
Insert the result of second query to a #temp table and join the #temp table to main table like below:
SELECT [id]
,[title]
,[desc]
FROM [localTest].[dbo].[main];
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME([Year]) from [localTest].[dbo].[Years] FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT [ID], ' + #cols + ' from (select [ID], [Year], [Amount] FROM [localTest].[dbo].[Years] ) x pivot (min([Amount]) for [Year] in (' + #cols + ')) p '
insert into #temp
execute(#query);
select * from [localTest].[dbo].[main] AS a inner join #temp as b on a.id = b.id

want order by LineSubType in pivat column

DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(LineSubType)
from TrnsSalaryProcessRegisterDetail
--inner join TrnsSalaryProcessRegister on TrnsSalaryProcessRegisterDetail.SRID=TrnsSalaryProcessRegister.Id
--where TrnsSalaryProcessRegisterDetail.LineValue!=null
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = '
select a.empid,a.payrollname,a.DepartmentName,s.PeriodName,
d.*
from TrnsSalaryProcessRegister s
inner join mstemployee a on a.id=s.empid
inner join
(
SELECT SRID,' + #cols + '
from
(
select SRID,LineSubType, LineValue
from TrnsSalaryProcessRegisterDetail
) x
pivot
(
sum(LineValue)
for LineSubType in (' + #cols + ')
) p
) d
on s.ID = d.SRID where s.PeriodName=''FY2017-Sep'' and a.payrollname=''EmcoStaff'' order by a.empid asc'
--print(#query)
execute(#query);
Just going off of what was provided here, you look like you want an ordered distinct list returned in a concatenated field ... Just add a group by and an order by which should return distinct values for LineSubeType so you likely will no longer need the distinct clause.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(LineSubType)
from TrnsSalaryProcessRegisterDetail
GROUP By QUOTENAME(LineSubType)
ORDER BY QUOTENAME(LineSubType)
--inner join TrnsSalaryProcessRegister on TrnsSalaryProcessRegisterDetail.SRID=TrnsSalaryProcessRegister.Id
--where TrnsSalaryProcessRegisterDetail.LineValue!=null
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = '
select a.empid,a.payrollname,a.DepartmentName,s.PeriodName,
d.*
from TrnsSalaryProcessRegister s
inner join mstemployee a on a.id=s.empid
inner join
(
SELECT SRID,' + #cols + '
from
(
select SRID,LineSubType, LineValue
from TrnsSalaryProcessRegisterDetail
) x
pivot
(
sum(LineValue)
for LineSubType in (' + #cols + ')
) p
) d
on s.ID = d.SRID where s.PeriodName=''FY2017-Sep'' and a.payrollname=''EmcoStaff'' order by a.empid asc'
--print(#query)
execute(#query);

SQL Pivot Issue, Need dynamic column names

Alright. So we needed to get output as down with the code below. I got most of the code from: Convert Rows to columns using 'Pivot' in SQL Server. This gives me the dynamic column names for the years and then counts the events for each year. I need (or at least would like) for the column names to formatted as FY 2014 Total etc. instead of just 2014. So created another list of column names to be used as the output names. I figured that when doing the pivot you would be giving the custom names for the new columns. I'm not sure what I would need to do.
DECLARE #colValues as NVARCHAR(MAX),
#colNames as NVARCHAR(MAX),
#query as NVARCHAR(MAX)
--Creates the column names dynamically from the FY results
select #colValues = STUFF((
SELECT ',' + QUOTENAME(FY)
From [dbo].[Table]
Group By FY
Order By FY desc
for xml path(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
select #colNames = STUFF((
SELECT ',' + '[FY ' + Cast(FY as NVARCHAR(4)) + ' Total]'
From [dbo].[Table]
Group By FY
Order By FY desc
for xml path(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
--print(#cols)
--Creates the SQL Query using pivot with the dynamic columns
set #query = '
with temp1 as
(
Select a.EventType,
a.Days_Since_Last_Event,
row_number() over (partition by a.EventType order by a.Days_Since_Last_Event) as ranking
From
(
SELECT EventType
,DATEDIFF(day,EventDate,GETDATE()) AS Days_Since_Last_Event
FROM [dbo].[Table]
) a join
(
SELECT EventType
,DATEDIFF(day,EventDate,GETDATE()) AS Days_Since_Last_Event
FROM [dbo].[Table]
) b on a.EventType = b.EventType and a.Days_Since_Last_Event = b.Days_Since_Last_Event
), temp3 as
(
select EventType,
Days_Since_Last_Event
from temp1
where ranking = 1
), temp2 as
(
Select EventType
,'+ #colNames + '
From
(
Select EventType, FY, 1 as thing
From [dbo].[Table]
) a
Pivot
(
Count(thing)
for FY in (' + #colValues + ')
) b
)
Select t3.*, '+ #colNames +'
From temp3 t3
join temp2 t2 on t3.EventType = t2.EventType'
execute(#query);
use #colValues in your temp2 cte in both places.. then use this in your final select.
select #colNames = STUFF((
SELECT ',' + QUOTENAME(FY) + ' AS [FY ' + Cast(FY as NVARCHAR(4)) + ' Total]'
From [dbo].[Table]
Group By FY
Order By FY desc
for xml path(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
should give you something like this..
DECLARE #colValues as NVARCHAR(MAX),
#colNames as NVARCHAR(MAX),
#query as NVARCHAR(MAX)
--Creates the column names dynamically from the FY results
select #colValues = STUFF((
SELECT ',' + QUOTENAME(FY)
From [dbo].[Table]
Group By FY
Order By FY desc
for xml path(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
select #colNames = STUFF((
SELECT ',' + QUOTENAME(FY) + ' AS [FY ' + Cast(FY as NVARCHAR(4)) + ' Total]'
From [dbo].[Table]
Group By FY
Order By FY desc
for xml path(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
--Creates the SQL Query using pivot with the dynamic columns
set #query = '
with temp1 as
(
Select a.EventType,
a.Days_Since_Last_Event,
row_number() over (partition by a.EventType order by a.Days_Since_Last_Event) as ranking
From
(
SELECT EventType
,DATEDIFF(day,EventDate,GETDATE()) AS Days_Since_Last_Event
FROM [dbo].[Table]
) a join
(
SELECT EventType
,DATEDIFF(day,EventDate,GETDATE()) AS Days_Since_Last_Event
FROM [dbo].[Table]
) b on a.EventType = b.EventType and a.Days_Since_Last_Event = b.Days_Since_Last_Event
), temp3 as
(
select EventType,
Days_Since_Last_Event
from temp1
where ranking = 1
), temp2 as
(
Select EventType
,'+ #colValues + '
From
(
Select EventType, FY, 1 as thing
From [dbo].[Table]
) a
Pivot
(
Count(thing)
for FY in (' + #colValues + ')
) b
)
Select t3.*, '+ #colNames +'
From temp3 t3
join temp2 t2 on t3.EventType = t2.EventType'
execute(#query);

Resources