2008年2月26日 星期二

SQL Server row formatting using PIVOT, UNPIVOT

Readers are advised to know that the technique described in a previous artivle: SQL Server string column concatenation is also used in here.

Suppose we a table t1 as follows:




IDProperty1Property2Property3Property4
17v1,v3v2v3,v5v2,v4,v6


Another table t2 as follows:









ValueDescription
v1eye
v2mouth
v3ear
v4nose
v5neck
v6hair



And we would like our output to be like this instead:




IDProperty1Property2Property3Property4
17eye,earmouthear,neckmouth,nose,hair



That is, the list of values from t1 has to be translated into more readable contents according to the correspondences in t2. Here are the steps:

1. UNPIVOT t1, converting rows into columns
2. insert converted data, combining with the corresponding values from t2, into temporary table #tmp
3. perform string concatenation
4. PIVOT the resulting table back to it original form

Here are the SQL commands for step 1:

select property, value
from
(
select * from t1 where ID = '17'
) AS p
UNPIVOT
(
value
for property
in (Property1, Property2, Property3, Property4)
) AS unpvt

resulting table:







propertyvalue
Property1v1,v3
Property2v2
Property3v3,v5
Property4v2,v4,v6


Here are the complete SQL commands for step 1 and 2:

create table #tmp(tmp_property varchar(10), tmp_description varchar(10), tmp_list varchar(100))

insert into #tmp(tmp_property, tmp_description, tmp_list)
select property, Description, NULL
from
(
select property, value
from
(
select * from t1 where ID = '17'
) AS p
UNPIVOT
(
value
for property
in (Property1, Property2, Property3, Property4)
) AS unpvt
) AS tmp
inner join t2 on value like '%' + t2.Description + '%'

resulting table:











tmp_propertytmp_descriptiontmp_list
Property1eyeNULL
Property1earNULL
Property2mouthNULL
Property3earNULL
Property3neckNULL
Property4mouthNULL
Property4noseNULL
Property4hairNULL


step 3:

update #tmp
set @list = tmp_list = (CASE WHEN @last <> tmp_property THEN tmp_description ELSE @list + ',' + tmp_description END), @last = tmp_property

resulting table:











tmp_propertytmp_descriptiontmp_list
Property1eyeeye
Property1eareye,ear
Property2mouthmouth
Property3earear
Property3neckear,neck
Property4mouthmouth
Property4nosemouth,nose
Property4hairmouth,nose,hair


step 4:

select *
from
(
select '17' as ID, tmp_property, max(tmp_list) as tmp_list from #tmp_default group by tmp_property
) as p
PIVOT
(
max(tmp_list)
for tmp_property
in (Property1, Property2, Property3, Property4)
) as pvt

resulting table:




IDProperty1Property2Property3Property4
17eye,earmouthear,neckmouth,nose,hair

沒有留言: