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);
Related
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
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?
Columns are not alphabetic because I can't use "order by" with "distinct".Please help me...
My Query :
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',MAX(CASE WHEN KullaniciAdi = ''' + p.KullaniciAdi + ''' THEN KisiAdi END) AS ' + QUOTENAME(p.KullaniciAdi)
FROM Populer p FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT top 100 ' + #cols + ' FROM ( SELECT KullaniciAdi,KisiAdi,ROW_NUMBER() OVER (PARTITION BY KullaniciAdi ORDER BY EklenmeTarihi) AS RowNum FROM Populer ) x GROUP BY RowNum '
EXECUTE(#query)
Results:
Of course you can. The key is to replace the distinct with group by. Then use order by:
SET #cols = STUFF((SELECT ', MAX(CASE WHEN KullaniciAdi = ''' + p.KullaniciAdi + ''' THEN KisiAdi END) AS ' + QUOTENAME(p.KullaniciAdi)
FROM Populer p
GROUP BY KullaniciAdi
ORDER BY p.KullaniciAdi
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'
), 1, 1, ''
) ;
One way around this is to make your query a derived table:
SELECT * FROM
(SELECT DISTINCT {the rest of your current query}) t
ORDER BY SomeColumn
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
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);