I currently have the following script which is pivoting results from rows into columns. It works a Great, apart from two issues;
I have a flag in another table which I want to filter by (basically: WHERE Table.Stats=YES). I'd normally do this in a basic query with an inner join followed by that WHERE statement. In the query below, I already have a WHERE FileSeq=25, which works, but this criteria I need to get working is calling on a different table.
The query is returning a lot of uncessary NULL fields.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(col+CAST(rn AS varchar(6)))
FROM
(
SELECT row_number() over(partition by UID ORDER BY ClassCode) rn
FROM dbo.StudentClasses
) d
CROSS APPLY
(
SELECT 'ClassCode', 1
) c (col, so)
GROUP BY col, rn, so
ORDER BY rn, so
FOR XML PATH(''), TYPE
).VALUE('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT UID,' + #cols + '
FROM
(
SELECT UID, col+CAST(rn AS varchar(10)) col, VALUE
FROM
(
SELECT UID, classcode,
row_number() over(partition by UID ORDER BY classcode) rn
FROM StudentClasses WHERE FileSeq=25
) t
CROSS APPLY
(
SELECT ''classcode'', CAST(classcode AS varchar(6))
) c (col, VALUE)
) x
PIVOT
(
MAX(VALUE)
for col in (' + #cols + ')
) p '
EXECUTE(#query)
Any assistance appreciated
Related
I have a dynamic pivot query that has dynamic columns column1, column 2... column
My query works fine. I can dump it into temp table ... But I wanted a view. I can't because of the changing number of columns. What do I do? It took long time to put this query together as I am not sql expert.
I would like to have a view of the result so I can link it to Access for the teams. I also have to create more queries in Access based on this link so the link can not disconnect. Any help will be appreciated
Below is my query.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'OriginalDx' then col+cast(seq as varchar(10))
else 'OriginalDx'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [HCCCodingBASEID]) seq
from [IDEAApplication].[HCCCoding].[OriginalDiagnosis]
) t
cross apply
(
select 'OriginalDx', 1
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [HCCCodingBASEID] AS ORIGINALDX_ID, ' + #cols + '
from
(
select t.[HCCCodingBASEID],
col = case
when c.col = ''OriginalDx'' then col+cast(seq as varchar(10))
else ''OriginalDx''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [OriginalDiagnosisCD],
row_number() over(partition by [HCCCodingBASEID]
order by [HCCCodingBASEID]) seq
from [IDEAApplication].[HCCCoding].[OriginalDiagnosis]
) t
cross apply
(
select ''OriginalDx'', [OriginalDiagnosisCD]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
----execute sp_executesql #query;
DECLARE #cols1 AS NVARCHAR(MAX),
#query1 AS NVARCHAR(MAX)
select #cols1 = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'DxAdded' then col+cast(seq as varchar(10))
else 'DxAdded'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [AddDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[AddDiagnosis]
) t1
cross apply
(
select 'DxAdded', 1 union all
select 'Reason', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query1 = 'SELECT [HCCCodingBASEID] AS DXADDED_ID, ' + #cols1 + '
from
(
select t1.[HCCCodingBASEID],
col = case
when c.col = ''DxAdded'' then col+cast(seq as varchar(10))
else ''DxAdded''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [AddDiagnosisCD], [AddReasonTXT],
row_number() over(partition by [HCCCodingBASEID]
order by [AddDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[AddDiagnosis]
) t1
cross apply
(
select ''DxAdded'', [AddDiagnosisCD] union all
select ''Reason'', [AddReasonTXT]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols1 + ')
) p '
------------------------------------------------------------------
DECLARE #cols2 AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX)
select #cols2 = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'DxDeleted' then col+cast(seq as varchar(10))
else 'DxDeleted'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [DeleteDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[DeleteDiagnosis]
) t2
cross apply
(
select 'DxDeleted', 1 union all
select 'Reason', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = 'SELECT [HCCCodingBASEID] AS DXDELETED_ID, ' + #cols2 + '
-----into ##tmp2
from
(
select t2.[HCCCodingBASEID],
col = case
when c.col = ''DxDeleted'' then col+cast(seq as varchar(10))
else ''DxDeleted''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [DeleteDiagnosisCD], [DeleteReasonTXT],
row_number() over(partition by [HCCCodingBASEID]
order by [DeleteDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[DeleteDiagnosis]
) t2
cross apply
(
select ''DxDeleted'', [DeleteDiagnosisCD] union all
select ''Reason'', [DeleteReasonTXT]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols2 + ')
) p '
-----------------------------------------------------merge all tables
----IF OBJECT_ID('tempdb..##TMP') IS NOT NULL
---DROP TABLE ##TMP
DECLARE #cmd NVARCHAR(MAX);
SET #cmd=N'
SELECT top 100 percent
A.*,
BB.PatientID as [Epic PatientID],
convert (varchar (10),AA.BirthDTS,101) as [Birth Date],
AA.SexDSC as [Sex],
BB.HospitalAccountBaseClassDSC as [Patient Type],
EE.payorNM AS [Payor Name],
B.*,
C.*,
D.*
--INTO ##TMP
FROM
[IDEAApplication].[HCCCoding].[HCCCoding] as A
LEFT JOIN ('+#query+') AS B
ON A.ID=B.ORIGINALDX_ID
LEFT JOIN ('+#query1+') AS C
ON A.ID=C.DXADDED_ID
LEFT JOIN ('+#query2+') AS D
ON A.ID=D.DXDELETED_ID
LEFT OUTER JOIN Epic.Finance.HospitalAccount_Enterprise AS BB
ON A.HospitalAccountID = BB.HospitalAccountID
LEFT JOIN Epic.Patient.Patient_Enterprise AS AA
ON BB.PatientID =AA.PatientID
LEFT JOIN Epic.Finance.HospitalAccount3_Enterprise AS CC
ON BB.HospitalAccountID = CC.HospitalAccountID
LEFT JOIN Epic.Reference.Payor AS EE
ON BB.PrimaryPayorID = EE.PayorID
order BY A.ID
;
';
EXECUTE (#cmd)
I am using Dynamic PIVOT approach to convert the dynamic rows into columns and its working fine for me. But I have one more requirement on top of it. I am using below query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ','
+ QUOTENAME(case when d.col = 'STN_CODE' then col+'_'+cast(seq as varchar(10))
else col+'_'+cast(seq as varchar(10)) end)
from ( select row_number() over(partition by POF_FILE_ID,
PART_PFX,
PART_BASE,PART_SFX
order by STN_CODE,PROCESS_ELEMENT) seq
from APT_POINT_OF_FIT
) t
cross apply
(
select 'STN_CODE', 1 union all
select 'PROCESS_ELEMENT', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT POF_FILE_ID,PART_PFX,PART_BASE,PART_SFX, ' +
#cols + '
from
(
select t.POF_FILE_ID,t.PART_PFX,t.PART_BASE,t.PART_SFX,
col = case
when c.col = ''STN_CODE'' then col+''_''+cast(seq as varchar(10))
else col+''_''+cast(seq as varchar(10))
end,
value
from
(
select POF_FILE_ID,PART_PFX,PART_BASE,PART_SFX,STN_CODE,
PROCESS_ELEMENT,
row_number() over(partition by POF_FILE_ID,
PART_PFX,
PART_BASE,
PART_SFX
order by STN_CODE) seq
from APT_POINT_OF_FIT
) t
cross apply
(
select ''STN_CODE'', STN_CODE union all
select ''PROCESS_ELEMENT'', PROCESS_ELEMENT
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute sp_executesql #query;
My requirement is to insert the values in separate columns till seq 8 and concatenate all other column values coming after that seq(> seq8).
Any help would be appreciated.
Thanks!
I have a table with a columns for case ID, Action, and reason.
a single case ID can have multiple rows with different actions and codes. I can pivot and get multiple rows with columns action1, action2, action3, etc., but for the life of me, can't get case id, action1, reason1, action2, reason2, etc on a single row.
If you need to go a little more dynamic (n reasons)
Drop Table #Temp
Declare #YourTable table (ID int,Action varchar(50),Reason varchar(50))
Insert Into #YourTable values
(1,'Load Data','Boss said to'),
(1,'Run Query','It is what I do'),
(2,'Take Garbage Out','Wife makes me')
-- Convert Data to EAV Structure'ish
Declare #XML xml = (Select *,GrpSeq = Row_Number() over (Partition By ID Order By (Select NULL)) from #YourTable for XML RAW)
Select ID = r.value('#ID','int')
,ColSeq = Row_Number() over (Partition By r.value('#ID','int') Order By (Select NULL))
,Element = attr.value('local-name(.)','varchar(100)')+r.value('#GrpSeq','varchar(10)')
,Value = attr.value('.','varchar(max)')
Into #Temp
From #XML.nodes('/row') as A(r)
Cross Apply A.r.nodes('./#*') AS B(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('ID','GrpSeq')
-- Get Cols in correct Order
Declare #Cols varchar(max)
Set #Cols = Stuff((Select ',' + QuoteName(Element)
From (Select Distinct Top 100 Percent ColSeq,Element From #Temp Order By ColSeq ) A
For XML Path(''), Type
).value('.', 'varchar(max)'),1,1,'')
-- Execute Dynamic Pivot
Declare #SQL varchar(max) = '
Select *
From (Select ID,Element,Value From #Temp) T
Pivot (
max(Value)
For [Element] in (' + #Cols + ')
) P '
Exec(#SQL)
Returns
I have the following table with the following sample data
ID Language Question SubQuestion SubSubQuestion TotalCount TotalPercent
3 E 9 0 1 88527 73%
3 E 9 0 2 19684 16%
3 E 9 0 3 12960 11%
3 E 9 0 9 933 1%
I want all in one row like this
ID Language TotalCount901 TotalPercent901 TotalCount902 TotalPercent902 TotalCount903 TotalPercent903
3 E 88527 73% 19684 16% 12960 11%
I've tired using the pivot command, but it dosnt to work for me.
I made a few assumptions based on your column names, but it looks like you want to use something similar to this. This applies both an UNPIVOT and then a PIVOT to get the values in the columns you requested:
select *
from
(
select id,
language,
col + cast(QUESTION as varchar(10))
+cast(subquestion as varchar(10))
+cast(SubSubQuestion as varchar(10)) col,
value
from
(
select id, language,
cast(TotalCount as varchar(10)) TotalCount,
totalPercent,
question, subquestion, SubSubQuestion
from yourtable
) usrc
unpivot
(
value
for col in (totalcount, totalpercent)
) un
) srcpiv
pivot
(
max(value)
for col in ([TotalCount901], [totalPercent901],
[TotalCount902], [totalPercent902],
[TotalCount903], [totalPercent903],
[TotalCount909], [totalPercent909])
) p
See SQL Fiddle with Demo
Note: when performing the UNPIVOT the columns need to be of the same datatype. If they are not, then you will need to convert/cast to get the datatypes the same.
If you have an unknown number of values to transform, you can use dynamic sql:
DECLARE #query AS NVARCHAR(MAX),
#colsPivot as NVARCHAR(MAX)
select #colsPivot
= STUFF((SELECT ','
+ QUOTENAME(c.name +
cast(QUESTION as varchar(10))
+cast(subquestion as varchar(10))
+cast(SubSubQuestion as varchar(10)))
from yourtable t
cross apply sys.columns as C
where C.object_id = object_id('yourtable') and
C.name in ('TotalCount', 'TotalPercent')
group by c.name, t.question, t.subquestion, t.subsubquestion
order by t.SubSubQuestion
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'select *
from
(
select id,
language,
col + cast(QUESTION as varchar(10))
+cast(subquestion as varchar(10))
+cast(SubSubQuestion as varchar(10)) col,
value
from
(
select id, language,
cast(TotalCount as varchar(10)) TotalCount,
totalPercent,
question, subquestion, SubSubQuestion
from yourtable
) usrc
unpivot
(
value
for col in (totalcount, totalpercent)
) un
) srcpiv
pivot
(
max(value)
for col in (' + #colsPivot + ')
) p '
execute(#query)
See SQL Fiddle with Demo
I have a typical RDMS setup where records in a main table can have optional records in a related table via a M2M join. I'm trying to PIVOT this data but in cases where there is no relation I want to return a default value. The join I have below is returning NULL.
select *
from
(
SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, 'Default') as Location
FROM dbo.ShopAssociations sa
INNER JOIN dbo.LookupAssociations la
ON sa.AssociationID = la.AssociationID
RIGHT JOIN dbo.Basic_Shop_Info s
ON sa.ShopID = s.ShopID
INNER JOIN dbo.Images i
ON la.ImageID = i.ImageID
) DataTable
PIVOT
(
min(Location)
for association in
([OnCall],[OCGuy],[ASCLogo],[ASC_OtherSt],[ASE],[AASP],[AASP_PA],
[ASE_BlueSeal],[AAA],[AAA-B],[ASA],[ATRA],[ICAR],[CAA],[ACDelco],
[Cert],[ASC],[BBB],[Goodyear],[Limos],[RVs],[Bosch],[NARSA],
[DiscTire],[BigO],[Tires],[Firestone],[ASCCA],[JustTires],[ASE_Blue])
) PivotTable
The output looks like this:
BizName OnCall OCGuy ASCLogo ASC_OtherSt ASE ...
"Wonderful Biz" somevalue somevalue NULL somevalue NULL
What I am trying to achieve is if a child record doesn't exist in INNER JOIN from Basic_Shop_Info to ShopAssociations that we get "Default" instead of NULL. I've tried ISNULL(), Coalesce() and even a CASE statement, all with the same results.
Based on your comment it sounds like you found a solution. I am only answering this to provide a suggestion based on the fact you are pivoting so many columns and they are all hard-coded. You can use dynamic SQL for a PIVOT and your query would look something like this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsPivot AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Name)
from dbo.LookupAssociations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsPivot = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(Name) +', ''Default'')'
from dbo.LookupAssociations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Bizname, ' + #colsPivot + ' from
(
SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, ''Default'') as Location
FROM dbo.ShopAssociations sa
INNER JOIN dbo.LookupAssociations la
ON sa.AssociationID = la.AssociationID
RIGHT JOIN dbo.Basic_Shop_Info s
ON sa.ShopID = s.ShopID
INNER JOIN dbo.Images i
ON la.ImageID = i.ImageID
) x
pivot
(
min(Location)
for association in (' + #cols + ')
) p
'
execute(#query)
The value #colsPivot is adding the IsNull() around each of you columns so you can put in place the Default value. But this should provide the same result as your original query where everything was hard-coded.
This will get the list of columns at run-time so then you do not have to hard-code anything and it will accept new values without having to change the query.
I got this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10)))
from
(
select row_number() over(partition by person_nbr
order by person_nbr,first_name, last_name, medication_name) rn
from TA_PIVOT
) d
cross apply
(
select 'diag' col, 1 sort
) c
group by col, rn, sort
order by rn, sort
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT person_nbr, first_name, last_name,medication_name,' + #cols + '
from
(
select person_nbr,first_name,last_name,medication_name,
col+cast(rn as varchar(10)) col,
value
from
(
-- when you perform an unpivot the datatypes have to be the same.
-- you might have to cast the datatypes in this query
select person_nbr,first_name,last_name, medication_name, cast(icd_code_id as varchar(500)) diag,
row_number() over(partition by person_nbr order by person_nbr, first_name, last_name,medication_name) rn
from ta_pivot
) src
unpivot
(
value
for col in (diag)
) unpiv
) d
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query);