How to convert rows into column in sql - sql

I have a table,
and need to convert it as
I have tried pivot but can't figure out please help me out .

Pivot does not work with more than one column out-of-the-box There are several approaches to solve this:
Use this table variable for all tests and please state your sample data always copy'n'pasteable. Best was a MCVE (Minimal Complete Verifyable Example) where you set up some code like mine here.
DECLARE #tbl TABLE(ID INT, Code INT,EmployeeName VARCHAR(100),ExamName VARCHAR(100),Board VARCHAR(100),Result VARCHAR(100));
INSERT INTO #tbl VALUES
(11537,12984,'TheName','SSC','b04','1st')
,(11537,12984,'TheName','HSC','b04','2nd')
,(11537,12984,'TheName','BA(H)','u33','2nd');
This is code to first concatenate your data to one single column. This allows PIVOT:
SELECT p.*
FROM
(
SELECT tbl.ID
,tbl.Code
,tbl.EmployeeName
,'Exam_' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.ID ORDER BY tbl.Code) AS VARCHAR(100)) AS ColName
,ExamName + ' (' + Board + '): ' + Result AS Concatenated
FROM #tbl AS tbl
) AS t
PIVOT
(
MIN(Concatenated) FOR ColName IN(Exam_1,Exam_2,Exam_3 /*add as many as you need*/)
) AS p
The result:
11537 12984 TheName SSC (b04): 1st HSC (b04): 2nd BA(H) (u33): 2nd
The next code does quite the same, but creates XML instead of plain text, which allows to separate your data afterwards:
SELECT p.ID
,p.Code
,p.EmployeeName
,E1
,E1.value('(/exam/#ExamName)[1]','varchar(100)') AS ExamName1
,E1.value('(/exam/#Board)[1]','varchar(100)') AS Board1
,E1.value('(/exam/#Result)[1]','varchar(100)') AS Result1
,E2
,E2.value('(/exam/#ExamName)[1]','varchar(100)') AS ExamName2
,E2.value('(/exam/#Board)[1]','varchar(100)') AS Board2
,E2.value('(/exam/#Result)[1]','varchar(100)') AS Result2
,E3
,E3.value('(/exam/#ExamName)[1]','varchar(100)') AS ExamName3
,E3.value('(/exam/#Board)[1]','varchar(100)') AS Board3
,E3.value('(/exam/#Result)[1]','varchar(100)') AS Result3
FROM
(
SELECT tbl.ID
,tbl.Code
,tbl.EmployeeName
,'Exam_' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.ID ORDER BY tbl.Code) AS VARCHAR(100)) AS ColName
,(SELECT ExamName AS [#ExamName],Board AS [#Board],Result AS [#Result] FOR XML PATH('exam')) AS AsXML
FROM #tbl AS tbl
) AS t
PIVOT
(
MIN(AsXML) FOR ColName IN(Exam_1,Exam_2,Exam_3 /*add as many as you need*/)
) AS p
OUTER APPLY
(
SELECT CAST(p.Exam_1 AS XML) AS E1
,CAST(p.Exam_2 AS XML) AS E2
,CAST(p.Exam_3 AS XML) AS E3
) AS CastedToXml
The result:
11537 12984 TheName <exam ExamName="SSC" Board="b04" Result="1st" /> SSC b04 1st <exam ExamName="HSC" Board="b04" Result="2nd" /> HSC b04 2nd <exam ExamName="BA(H)" Board="u33" Result="2nd" /> BA(H) u33 2nd
This is old-fashioned-pivot which is quite often better then normal pivot:
;WITH Numberd AS
(
SELECT *
,ROW_NUMBER() OVER(PARTITION BY tbl.ID ORDER BY tbl.Code) AS Number
FROM #tbl AS tbl
)
SELECT ID,Code,EmployeeName
,MAX(CASE WHEN Number=1 THEN ExamName END) AS ExamName1
,MAX(CASE WHEN Number=1 THEN Board END) AS Board1
,MAX(CASE WHEN Number=1 THEN Result END) AS Result1
,MAX(CASE WHEN Number=2 THEN ExamName END) AS ExamName2
,MAX(CASE WHEN Number=2 THEN Board END) AS Board2
,MAX(CASE WHEN Number=2 THEN Result END) AS Result2
,MAX(CASE WHEN Number=3 THEN ExamName END) AS ExamName3
,MAX(CASE WHEN Number=3 THEN Board END) AS Board3
,MAX(CASE WHEN Number=3 THEN Result END) AS Result3
FROM Numberd
GROUP BY ID,Code,EmployeeName
The last option was dynamic SQL...

Thnak you all , But My purpose is solved with this
SELECT
he.Id,he.Code,he.Name EmployeeName,en.Name [ExamName],bu.Name
[Board],[Result] = CASE WHEN
ac.GPA IS NULL THEN ac.Result ELSE CAST(ac.GPA AS VARCHAR) END,
ac.PassingYear
INTO #Temp
FROM H_Employee AS he
INNER JOIN
H_AcademicQualification AS ac ON ac.H_EmployeeId = he.Id
INNER JOIN
ExamName AS en ON en.Id = ac.ExamNameId
INNER JOIN
GroupSubject AS gs ON gs.Id = ac.GroupSubjectId
INNER JOIN
BoardUniversity AS bu ON bu.Id = ac.BoardUniversityId
Then
SELECT
a.id, a.Code, a.EmployeeName, a.ExamName, a.Board, a.Result, a.Passingyear,
b.ExamName, b.Board, b.Result, b.Passingyear,
c.ExamName, c.Board, c.Result, c.Passingyear,
d.ExamName, d.Board, d.Result, d.Passingyear
FROM
(SELECT
Id, Code, EmployeeName ,ExamName = CASE WHEN
ExamName LIKE 'S.S.%' THEN 'S.S.C' END,
Board=Board ,[Result]=CASE WHEN
Result IS NULL THEN Result ELSE CAST(Result AS VARCHAR) END,
Passingyear
FROM #temp
WHERE ExamName LIKE 'S.S.%') AS a
LEFT JOIN
(SELECT Id, Code, EmployeeName ,ExamName = CASE WHEN
ExamName LIKE 'H.S.%' THEN 'H.S.C' END,
Board=Board,[Result] = CASE WHEN
Result IS NULL THEN Result ELSE CAST(Result AS VARCHAR) END,
Passingyear
FROM #temp
WHERE ExamName LIKE 'H.S.%') AS b
ON a.Id=b.Id
LEFT JOIN
(SELECT Id, Code, EmployeeName ,ExamName = CASE WHEN
ExamName LIKE 'B.%' THEN 'Graduate' END,
Board=Board, [Result] = CASE WHEN
Result IS NULL THEN Result ELSE CAST(Result AS VARCHAR) END,
Passingyear
FROM #temp
WHERE ExamName LIKE 'B.%') AS c
ON a.Id=c.Id
LEFT JOIN
(SELECT Id, Code, EmployeeName, ExamName = CASE WHEN
ExamName LIKE 'M.%' THEN 'Post-Graduate' END,
Board=Board,[Result] = CASE WHEN
Result IS NULL THEN Result ELSE CAST(Result AS VARCHAR) END,
Passingyear
FROM #temp
WHERE ExamName LIKE 'M.%') AS d
ON a.Id=d.Id
Above query serve me purposes but will try #Shnugo Sample , Any way thank you all .

Related

How to pivot multiple columns without aggregation

I use SqlServer and i have to admit that i'm not realy good with it ...
This might be and easy question for the advanced users (I hope)
I have two tables which look like this
First table (ID isn't the primary key)
ID IdCust Ref
1 300 123
1 300 124
2 302 345
And the second (ID isn't the primary key)
ID Ref Code Price
1 123 A 10
1 123 Y 15
2 124 A 14
3 345 C 18
In the second table, the column "Ref" is the foreign key of "Ref" in the first table
I'm trying to produce the following output:
[EDIT]
The column "Stock", "Code" and "Price" can have x values, so I don't know it, in advance...
I tried so many things like "PIVOT" but it didn't give me the right result, so i hope someone can solve my problem ...
Use row_number() function and do the conditional aggregation :
select id, IdCust, Ref,
max(case when Seq = 1 then stock end) as [Stock A], -- second table *id*
max(case when Seq = 1 then code end) as [Code 1],
max(case when Seq = 1 then price end) as [Price1],
max(case when Seq = 2 then stock end) as [Stock B], -- second table *id*
max(case when Seq = 2 then code end) as [Code 2],
max(case when Seq = 2 then price end) as [Price2]
from (select f.*, s.Id Stock, s.Code, s.Price,
row_number() over (partition by f.Ref order by s.id) as Seq
from first f
inner join second s on s.Ref = f.Ref
) t
group by id, IdCust, Ref;
However, this would go with known values else you would need go with dynamic solution for that.
#YogeshSharma's provided an excellent answer.
Here's the same done using Pivot; SQL Fiddle Demo.
Functionally there's no difference between the two answers. However, Yogesh's solution's simpler to understand, and performs better; so personally I'd opt for that... I included this answer only because you mention PIVOT in the question:
select ft.Id
, ft.IdCust
, ft.Ref
, x.Stock1
, x.Code1
, x.Price1
, x.Stock2
, x.Code2
, x.Price2
from FirstTable ft
left outer join (
select Ref
, max([Stock1]) Stock1
, max([Stock2]) Stock2
, max([Code1]) Code1
, max([Code2]) Code2
, max([Price1]) Price1
, max([Price2]) Price2
from
(
select Ref
, Id Stock
, Code
, Price
, ('Stock' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) StockLineNo
, ('Code' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) CodeLineNo
, ('Price' + cast(Row_Number() over (partition by Ref order by Id, Code) as nvarchar)) PriceLineNo
from SecondTable
) st
pivot (max(Stock) for StockLineNo in ([Stock1],[Stock2])) pvtStock
pivot (max(Code) for CodeLineNo in ([Code1],[Code2])) pvtCode
pivot (max(Price) for PriceLineNo in ([Price1],[Price2])) pvtPrice
Group by Ref
) x
on x.Ref = ft.Ref
order by ft.Ref
Like Yogesh's solution, this will only handle as many columns as you specify; it won't dynamically alter the number of columns to match the data. For that you'd need to do dynamic SQL. However; if you need to do that, it's more likely you're attempting to solve the problem in the wrong way... so consider your design / determine if you really need additional columns per result rather than additional rows / some alternate approach...
Here's a Dynamic SQL implementation based on #YogeshSharma's answer: DBFiddle
declare #sql nvarchar(max) = 'select id, IdCust, Ref'
select #sql = #sql + '
,max(case when Seq = 1 then stock end) as [Stock' + rowNumVarchar + ']
,max(case when Seq = 1 then code end) as [Code' + rowNumVarchar + ']
,max(case when Seq = 1 then price end) as [Price' + rowNumVarchar + ']
'
from
(
select distinct cast(row_number() over (partition by ref order by ref) as nvarchar) rowNumVarchar
from second s
) z
set #sql = #sql + '
from (select f.*, s.Id Stock, s.Code, s.Price,
row_number() over (partition by f.Ref order by s.id) as Seq
from first f
inner join second s on s.Ref = f.Ref
) t
group by id, IdCust, Ref;
'
print #sql --see what the SQL produced is
exec (#sql)
(Here's a SQL Fiddle link for this one; but it's not working despite the SQL being valid

How to get data from 2 rows which has same data in all columns except one in MSSQL

As in my title I want to take data from 2 rows but In my case each 2nd row has one different value compare to the first row.
I want to take all the common data along with the different data as a single row .
Here you can see each row has same values in another row except the 2nd rows last column.
Thanks.
Edits Result :
I suspect you have a some kind of ordering columns that could specify your actual data ordering if so, then you can use row_number() function
select * from (
select *,
row_number() over (partition by <common data cols> order by ? desc) Seq
from table t
) t
where seq = 1;
EDIT : I don't believe your inventort_item_id columns but yes you could use creation_date for ordering purpose
SELECT
EPI.ITEM_CODE, LMP.PROD_DESC, LLPC.COLOC_PROD_PRICE,
BASE_PATH + '' + EPI.IMAGE_FOLDER_NAME + '/' + EPI.IMAGE_DESCRIPTION AS POPULAR_PRODUCTS_IMAGE_PATHS
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY ITEM_CODE ORDER BY creation_date DESC) as Seq
FROM ECOM_PRODUCT_IMAGES EPI
) EPI
INNER JOIN ECOM_POPULAR_PRODUCTS_MAPPING EPPIM ON EPPIM.ITEM_CODE = EPI.ITEM_CODE
INNER JOIN LOM_MST_PRODUCT LMP ON LMP.PROD_CODE = EPI.ITEM_CODE
INNER JOIN LOM_LNK_PROD_COMP LLPC ON LLPC.COLOC_PROD_CODE = LMP.PROD_CODE
WHERE EPI.Seq = 1 AND
EPPIM.ITEM_STATUS = 'ACTIVE';
EDIT 2: In that case you need to use GROUP BY clause with conditional aggregation
SELECT
EPI.ITEM_CODE, LMP.PROD_DESC, LLPC.COLOC_PROD_PRICE,
MAX(CASE WHEN EPI.Seq = 2
THEN (BASE_PATH + '' + EPI.IMAGE_FOLDER_NAME + '/' + EPI.IMAGE_DESCRIPTION)
END) AS POPULAR_PRODUCTS_IMAGE_PATHS,
MAX(CASE WHEN EPI.Seq = 1
THEN (BASE_PATH + '' + EPI.IMAGE_FOLDER_NAME + '/' + EPI.IMAGE_DESCRIPTION)
END) AS PATH_NEW
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY ITEM_CODE ORDER BY creation_date DESC) as Seq
FROM ECOM_PRODUCT_IMAGES EPI
) EPI
INNER JOIN ECOM_POPULAR_PRODUCTS_MAPPING EPPIM ON EPPIM.ITEM_CODE = EPI.ITEM_CODE
INNER JOIN LOM_MST_PRODUCT LMP ON LMP.PROD_CODE = EPI.ITEM_CODE
INNER JOIN LOM_LNK_PROD_COMP LLPC ON LLPC.COLOC_PROD_CODE = LMP.PROD_CODE
WHERE EPPIM.ITEM_STATUS = 'ACTIVE'
GROUP BY EPI.ITEM_CODE, LMP.PROD_DESC, LLPC.COLOC_PROD_PRICE;
here is my approach, also using a window function.
sample data
if object_id('tempdb..#x') is not null drop table #x
CREATE TABLE #x (ITEM_CODE VARCHAR(10), PROD_DESC VARCHAR(20),
COLOR_PROD_PRICE DECIMAL, POPULAR_PRODUCTS_IMAGE_PATHS VARCHAR(200))
INSERT INTO #X(ITEM_CODE,PROD_DESC,COLOR_PROD_PRICE,POPULAR_PRODUCTS_IMAGE_PATHS) VALUES
('P0001', 'Axe Brand', 88.000, 'some_path_to_img1.jpg'),
('P0001', 'Axe Brand', 88.000, 'some_path_to_img2.jpg'),
('P0002', 'Almond Nuts', 499.000, 'some_path_to_img1.jpg'),
('P0002', 'Almond Nuts', 499.000, 'some_path_to_img2.jpg')
query - just change #x to your table and it should work
;WITH my_cte as
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY ITEM_CODE ORDER BY POPULAR_PRODUCTS_IMAGE_PATHS) AS 'track_row'
FROM #x
)
SELECT a.ITEM_CODE, a.PROD_DESC, a.COLOR_PROD_PRICE,
a.POPULAR_PRODUCTS_IMAGE_PATHS + ' ' + b.POPULAR_PRODUCTS_IMAGE_PATHS AS 'POPULAR_PRODUCTS_IMAGE_PATHS'
FROM my_cte AS a
INNER JOIN
my_cte AS b ON a.ITEM_CODE=b.ITEM_CODE
WHERE a.track_row=1 AND b.track_row=2
output
ITEM_CODE PROD_DESC COLOR_PROD_PRICE POPULAR_PRODUCTS_IMAGE_PATHS
P0001 Axe Brand 88 some_path_to_img1.jpg some_path_to_img2.jpg
P0002 Almond Nuts 499 some_path_to_img1.jpg some_path_to_img2.jpg

How to merge two columns from CASE STATEMENT of DIFFERENT CONDITION

My expected result should be like
----invoiceNo----
T17080003,INV14080011
But right now, I've come up with following query.
SELECT AccountDoc.jobCode,AccountDoc.shipmentSyskey,AccountDoc.docType,
CASE AccountDoc.docType
WHEN 'M' THEN
JobInvoice.invoiceNo
WHEN 'I' THEN
(STUFF((SELECT ', ' + RTRIM(CAST(AccountDoc.docNo AS VARCHAR(20)))
FROM AccountDoc LEFT OUTER JOIN JobInvoice
ON AccountDoc.principalCode = JobInvoice.principalCode AND
AccountDoc.jobCode = JobInvoice.jobCode
WHERE (AccountDoc.isCancelledByCN = 0)
AND (AccountDoc.docType = 'I')
AND (AccountDoc.jobCode = #jobCode)
AND (AccountDoc.shipmentSyskey = #shipmentSyskey)
AND (AccountDoc.principalCode = #principalCode) FOR XML
PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' '))
END AS invoiceNo
FROM AccountDoc LEFT OUTER JOIN JobInvoice
ON JobInvoice.principalCode = AccountDoc.principalCode AND
JobInvoice.jobCode = AccountDoc.jobCode
WHERE (AccountDoc.jobCode = #jobCode)
AND (AccountDoc.isCancelledByCN = 0)
AND (AccountDoc.shipmentSyskey = #shipmentSyskey)
AND (AccountDoc.principalCode = #principalCode)
OUTPUT:
----invoiceNo----
T17080003
INV14080011
Explanation:
I want to select docNo from table AccountDoc if AccountDoc.docType = I.
Or select invoiceNo from table JobInvoice if AccountDoc.docType = M.
The problem is what if under same jobCode there have 2 docType which are M and I, how I gonna display these 2 invoices?
You can achieve this by using CTE and FOR XML. below is the sample code i created using similar tables you have -
Create table #AccountDoc (
id int ,
docType char(1),
docNo varchar(10)
)
Create table #JobInvoice (
id int ,
invoiceNo varchar(10)
)
insert into #AccountDoc
select 1 , 'M' ,'M1234'
union all select 2 , 'M' ,'M2345'
union all select 3 , 'M' ,'M3456'
union all select 4 , 'I' ,'I1234'
union all select 5 , 'I' ,'I2345'
union all select 6 , 'I' ,'I3456'
insert into #JobInvoice
select 1 , 'INV1234'
union all select 2 , 'INV2345'
union all select 3 , 'INV3456'
select *
from #AccountDoc t1 left join #JobInvoice t2
on t1.id = t2.id
with cte as
(
select isnull( case t1.docType WHEN 'M' THEN t2.invoiceNo WHEN 'I' then
t1.docNo end ,'') invoiceNo
from #AccountDoc t1 left join #JobInvoice t2
on t1.id = t2.id )
select invoiceNo + ',' from cte For XML PATH ('')
You need to pivot your data if you have situations where there are two rows, and you want two columns. Your sql is a bit messy, particularly the bit where you put an entire select statement inside a case when in the select part of another query. These two queries are virtually the same, you should look for a more optimal way of writing them. However, you can wrap your entire sql in the following:
select
Jobcode, shipmentsyskey, [M],[I]
from(
--YOUR ENTIRE SQL GOES HERE BETWEEN THESE BRACKETS. Do not alter anything else, just paste your entire sql here
) yoursql
pivot(
max(invoiceno)
for docType in([M],[I])
)pvt

Pivot outputs two values

create table #Contact(
LoanNumber int,
ContactType varchar(10),
CompanyName varchar(10),
CompanyPhone varchar(10),
CONSTRAINT PK PRIMARY KEY (LoanNumber,ContactType)
)
Insert into #Contact
values (1,'Appriaser','Yige King','11' ),
(1,'AssetOwner','gqqnbig','22' )
This is my table. ContactTypes are only Appriaser and AssetOwner.
Can I get a table like
LoanNumber AppraiserCompanyName AppraiserCompanyPhone AssertOwnerCompanyName AssertOwnerCompanyPhone
----------------------------------------------------------------------------------------------------
6103339 YigeKing 11 gqqnbig 22
I managed to write this
select LoanNumber,
CompanyNamePT.Appriaser as AppriaserCompanyName, CompanyNamePT.AssetOwner as AssetOwnerCompanyName
--CompanyPhonePT.Appriaser as AppriaserCompanyPhone, CompanyPhonePT.AssetOwner as AssetOwnerCompanyPhone
from (
select #contact.LoanNumber, #contact.ContactType, #contact.CompanyName
from #contact
) as c
pivot ( max(c.CompanyName) for c.ContactType in (Appriaser,AssetOwner)) as CompanyNamePT
--pivot ( max(c.CompanyPhone) for c.ContactType in ([Appriaser],[AssetOwner])) as CompanyPhonePT
It outputs company names, but if I uncomment the two lines to get phone number, it throws syntax error.
How can I make it work? Ideally I want to use pivot because I'm learnig it.
For the desired PIVOT
Select *
From (
Select C.LoanNumber
,B.*
From #Contact C
Cross Apply ( values (IIF(ContactType='Appriaser' ,'AppraiserCompanyName' , 'AssetOwnerCompanyName') ,C.CompanyName)
,(IIF(ContactType='Appriaser' , 'AppraiserCompanyPhone', 'AssetOwnerCompanyPhone'),C.CompanyPhone)
) B (Item,Value)
) A
pivot ( max(A.Value) for A.Item in ([AppraiserCompanyName],[AppraiserCompanyPhone],[AssetOwnerCompanyName],[AssetOwnerCompanyPhone]) ) P
But a Conditional Aggregation would do as well
Select C.LoanNumber
,AppraiserCompanyName = max(case when ContactType='Appriaser' then C.CompanyName end)
,AppraiserCompanyPhone = max(case when ContactType='Appriaser' then C.CompanyPhone end)
,AssetOwnerCompanyName = max(case when ContactType='AssetOwner' then C.CompanyName end)
,AssetOwnerCompanyPhone = max(case when ContactType='AssetOwner' then C.CompanyPhone end)
From #Contact C
Group By C.LoanNumber
Both Would Return
If it Helps with the Visualization, the sub-query with the Cross Apply Generates

Dynamic SubSelects in SQL Select Statement

I am querying a table for some basic information, file number, case type, status, etc. In addition I need a column for every single one of 138 case status types that will display the date the case had that status. Here is a sample:
SELECT FileNum,
CaseType,
CurrentCaseStatus,
(SELECT TOP 1 EventDt FROM caseStatusHistory WHERE CaseID = c.caseID AND CaseStatus = 'CS001' ORDER BY EventDt DESC) AS [Charge - Phone],
(SELECT TOP 1 EventDt FROM caseStatusHistory WHERE CaseID = c.caseID AND CaseStatus = 'CS002' ORDER BY EventDt DESC) AS [Charge - Written],
-- 136 more just like the live above
FROM Case c
I can query another table for all the case status types:
SELECT Code, Description
FROM caseStatus
WHERE Code BETWEEN 'CS001' AND 'CS138'
ORDER BY Code
How can I dynamically create each of those columns instead of having to manually write 138 select statements?
That's going to be terribly slow -- 138 correlated subqueries. I think you can achieve the same result with an OUTER JOIN and a GROUP BY with MAX and CASE:
Select c.filenum,
c.casetype,
c.currentcasestatus,
max(case when csh.CaseStatus = 'CS001' then EventDt end) as [Charge - Phone],
max(case when csh.CaseStatus = 'CS002' then EventDt end) as [Charge - Written]
from case c
left join casestatushistory csh on c.caseid = csh.caseid
group by c.filenum,
c.casetype,
c.currentcasestatus
BTW, I would suggest just writing the statement out -- it won't take that long and it will out perform a dynamic sql approach. I'm not completely sure how you'd get your column names with dynamic sql either unless Phone and Written are in another column.
Try using a PIVOT. The SQL below should work -
--Select the pivot data into a temp table
SELECT c.caseID,
c.FileNum,
c.CaseType,
c.CurrentCaseStatus,
csh.EventDt,
cs.Description
INTO #StatusDates
FROM [Case] c
LEFT JOIN caseStatusHistory csh
ON csh.caseID = c.caseID
LEFT JOIN caseStatus cs
ON cs.Code = csh.CaseStatus
--From the pivot data, get the list of field names (assumes description field is the source for the field name)
DECLARE #statusDescriptions VARCHAR(MAX)
SET #statusDescriptions = ''
SELECT #statusDescriptions = COALESCE(#statusDescriptions+'[','') + Description
FROM (
SELECT DISTINCT Description
FROM #StatusDates
WHERE Description IS NOT NULL
) x
SET #statusDescriptions = REPLACE(#statusDescriptions, '[', '],[') + ']'
SET #statusDescriptions = SUBSTRING(#statusDescriptions, 3, LEN(#statusDescriptions))
--Create a SQL statement to pivot the data into the fields.
DECLARE #sql VARCHAR(MAX)
SET #SQL = '
SELECT *
FROM #StatusDates
PIVOT(MIN(EventDt)
FOR Description IN (' + #statusDescriptions + '))
AS PVTTable '
PRINT #sql
EXEC(#sql)
DROP TABLE #StatusDates