Pivot SQL with top 1 - sql

I have a simple table, with scan data in rows.
I want to pivot the dataset, with the first scan in each phase_key.
Into this:
I use this sql:
select
d.shipment_id,
d.carrier_reference,
e.phase_key,
e.event,
CONVERT(DATETIME,e.time) AS ScanDate
from
data d
inner join event e on d.id = e.data_id
where
shipment_id = '99156136'
order by e.time asc
I have tried using the suggested sql. (adding 1 id, to verify format. But it loads without the code suggested from #gotqn.
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SELECT #DynamicPIVOTColumns = STRING_AGG(CAST(QUOTENAME([phase_key]) AS VARCHAR(MAX)), ',') WITHIN GROUP (ORDER BY [phase_key])
FROM
(
SELECT DISTINCT [phase_key]
FROM data d
inner join event e on d.id = e.data_id
) DS ([phase_key]);
SET #DynammicTSQLStatement = N'
SELECT *
FROM
(
SELECT shipment_id
,phase_key
,time
FROM data d
inner join event e on d.id = e.data_id
where
shipment_id = "99156136"
) DS
PIVOT
(
MAX([time]) FOR [phase_key] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;
But after 2mins it still have not loaded the 1. id om trying as a sample.

Try this:
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SELECT #DynamicPIVOTColumns = STRING_AGG(CAST(QUOTENAME([phase_key]) AS VARCHAR(MAX)), ',') WITHIN GROUP (ORDER BY [phase_key])
FROM
(
SELECT DISTINCT [phase_key]
FROM [my_table]
) DS ([phase_key]);
SET #DynammicTSQLStatement = N'
SELECT *
FROM
(
SELECT shipment_id
,phase_key
,ScanDate
FROM [my_table]
) DS
PIVOT
(
MAX([ScanDate]) FOR [phase_key] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;

Related

SQL Server 2016: Turn multiple lines into columns with the different iterations

I have a table that has many InsuranceNo's for unique MemberIDs. If there are more than one InsuranceNo, I want the InsuranceNo's to shift to a column, so in the end there is one line per MemberID, with all the iterations of that ID's InsuranceNo's as a Column.
MemberID InsuranceNo
--------------------------
123456 dser
124571 jklh
123456 abcd
I want it to look like this:
MemberID InsuranceNo1 InsuranceNo2
-----------------------------------------------------
123456 dser abcd
124571 jklh
Thank you!
Yet another option... Just change "YourTable" to your actual table name.
Example
Declare #SQL varchar(max) = '
Select *
From (
Select MemberID
,Item = concat(''InsuranceNo'',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in (' + Stuff((Select ','+QuoteName(concat('InsuranceNo',ColNr))
From (Select Distinct ColNr=row_number() over (Partition By MemberID Order By (Select NULL)) from YourTable ) A
For XML Path('')),1,1,'') + ') ) p'
--Print #SQL
Exec(#SQL);
Returns
MemberID InsuranceNo1 InsuranceNo2
123456 dser abcd
124571 jklh NULL
If it helps wrap your head around PIVOT, the SQL Generated looks like this:
Select *
From (
Select MemberID
,Item = concat('InsuranceNo',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in ([InsuranceNo1],[InsuranceNo2]) ) p
I prefer a dynamic cross tab to the dynamic pivot. I find the syntax far less obtuse and it is super easy if you need to add additional columns. Here is I would go about tackling this. Of course in your case you don't need a temp table because you have an actual table to use.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
MemberID int
, InsuranceNo varchar(10)
)
insert #Something values
(123456, 'dser')
, (124571, 'jklh')
, (123456, 'abcd')
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by MemberID order by InsuranceNo) as RowNum
from #Something
)
select MemberID';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by MemberID order by MemberID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then InsuranceNo end) as InsuranceNo' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by MemberID
order by COUNT(*) desc
)
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute

how to display data with dynamic columns -SQL

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)

Can I pivot dynamic table with no group by in SQL Server

This is my data in table (left join from field table and value table)
This is my expected result table after use pivot function
Thanks for help ^___^
I suggest you to use dynamic SQL as fieldnames number may very in future:
DECLARE #columns nvarchar(max),
#sql nvarchar(max)
SELECT #columns = COALESCE(#columns,'') + ',' + QUOTENAME(c.fieldname)
FROM [Columns] c
ORDER BY c.cid
SELECT #sql = N'
SELECT *
FROM (
SELECT v.[row],
c.fieldname,
v.fieldvalue
FROM [Values] v
INNER JOIN [Columns] c
ON v.cid = c.cid
) t
PIVOT (
MAX(fieldvalue) FOR fieldname IN ('+STUFF(#columns,1,1,'')+')
) pvt'
EXEC sp_executesql #sql
Will output:
row FirstName LastName Email Phone
1 Arnun Saelim Arnun.s#outlook.com 0922743838
2 Micheal Saelim Micheal#gmail.com 0886195353
I'm not sure why group by got into your mind, but here is a working example of what you are trying to achieve.
select * into #temp from
( values
(1,'A','AV'),
(1,'B','BV'),
(1,'C','CV'),
(2,'A','AV'),
(2,'B','BV'),
(2,'C','CV'))
as t(row, FieldName, FieldValue)
select *
from #temp
PIVOT
(MAX(FieldValue) FOR FieldName in ([A],[B],[C])) as pvt
Does that work for you?

How do I pivot query using UNION ALL

I have following table structure & below is the Query i am executing :-
Following are the tables :-
First Table :-
Second Table :-
SELECT Code, Fname, OTHINC1, OTHINC2
FROM (SELECT a.FieldName
,a.YearlyValue
,b.Code
,b.Fname
FROM [TaxOtherIncome] AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE a.EntryDate = '2014-12-01') x
PIVOT (MAX(YearlyValue) FOR FieldName IN (OTHINC1,OTHINC2)) p
Result i am getting :-
I also want Records from the Second table i mentioned above. So In my final Result Columns SUBFLD36
SUBFLD37 & House_Rent will be added.
As i am new to Pivot, Help me to modify above query to get expected results.
Consider you are inserting the result after your join to a temporary table which is the below
Declare a variable for getting the columns to pivot
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + [FIELD NAME] + ']',
'[' + [FIELD NAME] + ']')
FROM (SELECT DISTINCT [FIELD NAME] FROM #TEMP) PV
ORDER BY [FIELD NAME]
Now pivot it
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT * FROM
(
SELECT * FROM #TEMP
) x
PIVOT
(
MAX([YEARLY VALUE])
FOR [FIELD NAME] IN (' + #cols + ')
) p
'
EXEC SP_EXECUTESQL #query
Click here to view the result
RESULT
You can try this:
SELECT Code, Fname, OTHINC1, OTHINC2, SUBFLD36, SUBFLD37, House_Rent
FROM (SELECT a.FieldName
,a.YearlyValue
,b.Code
,b.Fname
FROM [TaxOtherIncome] AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE a.EntryDate = '2014-12-01'
UNION
SELECT a.FieldName
,a.FieldValue AS YearlyValue
,a.EmployeeCode AS Code
,b.Fname
FROM SecondTable AS a
INNER JOIN [EmployeeDetail] AS b
ON a.EmployeeId = b.Id
WHERE EntryDate = '2014-12-01') x
PIVOT (MAX(YearlyValue) FOR FieldName IN (OTHINC1, OTHINC2, SUBFLD36, SUBFLD37, House_Rent)) p

How to declare the columns dynamically in a Select query using PIVOT

I am writing a query to get the address for PersonID. Following query is working for me but it only returns with two Addresses. I want to handle the 'n' number of address with a single query. Is there any way to do this?
Many thanks
SELECT
PersonID, PersonName
[Address1], [Address2]
FROM
(
SELECT
P.PersonID,
P.PersonName,
(ROW_NUMBER() OVER(PARTITION BY P.PersonID ORDER BY A.AddressID)) RowID
FROM tblPerson
INNER JOIN tblAddress AS A ON A.PersonID = P.PersonID
) AS AddressTable
PIVOT
(
MAX(AddressID)
FOR RowID IN ([Address1], [Address2])
) AS PivotTable;
Assuming the following tables and sample data:
USE tempdb;
GO
CREATE TABLE dbo.tblPerson(PersonID INT, PersonName VARCHAR(255));
INSERT dbo.tblPerson SELECT 1, 'Bob'
UNION ALL SELECT 2, 'Charlie'
UNION ALL SELECT 3, 'Frank'
UNION ALL SELECT 4, 'Amore';
CREATE TABLE dbo.tblAddress(AddressID INT, PersonID INT, [Address] VARCHAR(255));
INSERT dbo.tblAddress SELECT 1,1,'255 1st Street'
UNION ALL SELECT 2,2,'99 Elm Street'
UNION ALL SELECT 3,2,'67 Poplar Street'
UNION ALL SELECT 4,2,'222 Oak Ave.'
UNION ALL SELECT 5,1,'36 Main Street, Suite 22'
UNION ALL SELECT 6,4,'77 Sicamore Ct.';
The following query gets the results you want, and shows how it handles 0, 1 or n addresses. In this case the highest number is 3 but you can play with more addresses if you like by adjusting the sample data slightly.
DECLARE #col NVARCHAR(MAX) = N'',
#sel NVARCHAR(MAX) = N'',
#from NVARCHAR(MAX) = N'',
#query NVARCHAR(MAX) = N'';
;WITH m(c) AS
(
SELECT TOP 1 c = COUNT(*)
FROM dbo.tblAddress
GROUP BY PersonID
ORDER BY c DESC
)
SELECT #col = #col + ',[Address' + RTRIM(n.n) + ']',
#sel = #sel + ',' + CHAR(13) + CHAR(10) + '[Address' + RTRIM(n.n) + '] = x'
+ RTRIM(n.n) + '.Address',
#from = #from + CHAR(13) + CHAR(10) + ' LEFT OUTER JOIN xMaster AS x'
+ RTRIM(n.n) + ' ON x' + RTRIM(n.n) + '.PersonID = p.PersonID AND x'
+ RTRIM(n.n) + '.rn = ' + RTRIM(n.n)
FROM m CROSS JOIN (SELECT n = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_columns) AS n WHERE n.n <= m.c;
SET #query = N';WITH xMaster AS
(
SELECT PersonID, Address,
rn = ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY Address)
FROM dbo.tblAddress
)
SELECT PersonID, PersonName' + #col
+ ' FROM
(
SELECT p.PersonID, p.PersonName, ' + STUFF(#sel, 1, 1, '')
+ CHAR(13) + CHAR(10) + ' FROM dbo.tblPerson AS p ' + #from + '
) AS Addresses;';
PRINT #query;
--EXEC sp_executesql #query;
If you print the SQL you will see this result:
;WITH xMaster AS
(
SELECT PersonID, Address,
rn = ROW_NUMBER() OVER (PARTITION BY PersonID ORDER BY Address)
FROM dbo.tblAddress
)
SELECT PersonID, PersonName,[Address1],[Address2],[Address3] FROM
(
SELECT p.PersonID, p.PersonName,
[Address1] = x1.Address,
[Address2] = x2.Address,
[Address3] = x3.Address
FROM dbo.tblPerson AS p
LEFT OUTER JOIN xMaster AS x1 ON x1.PersonID = p.PersonID AND x1.rn = 1
LEFT OUTER JOIN xMaster AS x2 ON x2.PersonID = p.PersonID AND x2.rn = 2
LEFT OUTER JOIN xMaster AS x3 ON x3.PersonID = p.PersonID AND x3.rn = 3
) AS Addresses;
If you execute it, you will see this:
I know the query to get here is an ugly mess, but your requirement dictates it. It would be easier to return a comma-separated list as I suggested in my comment, or to have the presentation tier deal with the pivoting.