Developing Matt

My Technical Journal

Pivot Without Aggregation or Aggravation

leave a comment »

I needed to flip my data horizontally.  I didn’t need to aggregate anything.  I was just working with a user that wanted the data to look different.

Instead of this

Car Tire
Car Window
Car Wipers
Car Engine
Car Air Freshener

 

He wanted

  col1 col2 col3 col4 col5
Car Tire Window Wipers Engine Air Freshener

 

The pivot command requires an aggregate.  It’s the basis of the command. When you are pivoting you are saying ‘hey give me some number crunching for this particular arrangement of data:

PIVOT (calculation(on what) for the following column headings (column A, column B, column C) as pvt

So how can this be done without aggregating?  Well if your group has only one calculation then you can do whatever calculation you want.  For example, the average of 62 will always be 62.  So using the rownumber in conjunction with a max on a string we can cheat and get the pivot command to give us what we want.

I was so close to figuring this out when I found a great post by Arie Stern here.  I used his post to get this concept working.  Thank you Mr. Stern for your assistance.

Set up your table here for this example:

create table #rrr(vehicle varchar(20), part varchar(20))
insert into #rrr values(‘CAR’,’Tire’)
insert into #rrr values(‘CAR’,’Window’)
insert into #rrr values(‘CAR’,’Wiper’)
insert into #rrr values(‘CAR’,’Engine’)
insert into #rrr values(‘CAR’,’Air Freshener’)
Select * from #rrr

The way to pivot this data is as follows:

select vehicle, [1], [2], [3],[4],[5]
from
(Select vehicle, part, Row_number() over (partition by vehicle order by vehicle) as rownum from #rrr)
a
pivot (max(part) for rownum in ([1],[2],[3],[4],[5])) as pvt

Note that I am using the rownumber to get my column headings and am using max for the part types.  So this works great, of course, only if you know how many rows there are per vehicle.  Restated: the above works only because I know there are only 5 rows of data. Data is hardly this friendly.  So the catch is: if you don’t know how many rows you will have you will have to build your sql out of dynamic sql.  If you are careful you won’t be writing dynamic sql inside of dynamic sql which will either drive you mad or will drive the person mad behind you that has to maintain your code.  Regardless, here is how you would do it.  :

———-step 1: set up your column names based upon rownumber———————-
declare @rownum varchar(50)
set @rownum = ”
select @rownum = @rownum + ‘[‘ +  cast(rownum as char(1))+ ‘],’
from
(Select vehicle, part, Row_number() over (partition by vehicle order by vehicle) as rownum from #rrr)
a
set @rownum = left(@rownum, len(@rownum)-1)
print @rownum
–Note that i’m using brackets around column headings.  You could add a more descriptive
–column name but will have to cast your rownumbers later on (Just wanted to keep it as simple as possible).
–Also, note that you have to strip the last comma from your column list

———-step 2: create and call your dynamic sql using your new rownumber variable———–
declare @sql varchar(1000)
set @sql =
‘SELECT vehicle, ‘ + @rownum + ‘
from
(Select vehicle, part, Row_number() over (partition by vehicle order by vehicle) as rownum from #rrr
) a
pivot (max(part) for rownum in (‘ + @rownum + ‘)) as pvt   

print @sql
execute (@sql)

Watercolors 1

Advertisements

Written by matt

November 2, 2011 at 4:09 pm

Posted in T-Sql

Tagged with

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: