Showing posts with label SQL 2005. Show all posts
Showing posts with label SQL 2005. Show all posts

Tuesday, July 01, 2008

SQL Server 2005 PIVOT Operator

For my current project I needed to convert rows of data to columns. I learned how to do this with the SQL Server 2005 PIVOT Operator.

Here's the original code...

SELECT p.user_id, pit.data_name, pi.item_value
FROM profile p
JOIN profile_item pi ON pi.profile_id = p.profile_id
JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100

...and the original results...

p.user_id  pit.data_name        pi.item_value
---------  -------------        -------------
100        age                  Under 18
100        gender               Male
100        marital_status       Single
100        family_size          1
100        household_income     Under $15,000
100        ethnicity            Rather not disclose

...and now the new SQL using the PIVOT operator...

SELECT *
FROM (SELECT p.user_id, pit.data_name, pi.item_value
          FROM profile p
          JOIN profile_item pi ON pi.profile_id = p.profile_id
          JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
          AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100)m
PIVOT (MAX(item_value) FOR data_name IN ([age],[gender],[marital_status],[family_size],[household_income],[ethnicity]))p

...and the desired results...

p.user_id  age        gender    marital_status   family_size  household_income   ethnicity
---------  ---        ------    --------------   -----------  ----------------   ---------
100        Under 18   Male      Single           1            Under $15,000      Rather not disclose

You could also cross tab this without using pivot operator...

SELECT p.user_id,
MAX(CASE WHEN pit.data_name='age' THEN pi.item_value ELSE NULL END) AS age,
MAX(CASE WHEN pit.data_name='gender' THEN pi.item_value ELSE NULL END) AS gender,
MAX(CASE WHEN pit.data_name='marital_status' THEN pi.item_value ELSE NULL END) AS marital_status,
MAX(CASE WHEN pit.data_name='family_size' THEN pi.item_value ELSE NULL END) AS family_size,
MAX(CASE WHEN pit.data_name='household_income' THEN pi.item_value ELSE NULL END) AS household_income,
MAX(CASE WHEN pit.data_name='ethnicity' THEN pi.item_value ELSE NULL END) AS ethnicity
FROM profile p
JOIN profile_item pi ON pi.profile_id = p.profile_id
JOIN profile_item_type pit ON pit.profile_item_type_id = pi.profile_item_type_id
AND pit.data_name in ('age','gender','marital_status','family_size','household_income','ethnicity')
WHERE p.user_id = 100
GROUP BY p.user_id