Enjoy Every Sandwich

Thoughts on SQL, XML, .NET and sometimes beer.

<August 2008>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456


Navigation

Tools

List O'Links

Kent's Other Stuff

Subscriptions

News

Please read these
Notices and Disclamiers

Post Categories

Article Categories



Wednesday, September 13, 2006 - Posts

What being clumsy taught me about joining matrices
Those of you who've met me probably have figured out that I'm not the most agile person ever. One time in Gym class, when they were trying to get me to play basketball, the coach said "you're the only kid I've ever known who can't pivot." I never thought this would come back to haunt me (its not like I try to play basketball), but it did recently when working with a matrix. Its not hard to imagine treating a table in SQL Server as a matrix. What is hard -- or at least is a lot of code to write -- is doing a join on matrix to some other table. Consider for example the case of an Italian resturant. They've decided to use SQL Server to manage a number of things and a couple of them are lists of dished they prepare and a table that organizes these dishes into four-course meals. The tables might be structured something like this:
create table dbo.menuItems (itemID tinyint identity(1,1) primary key,name varchar(30) not null unique,meatless bit not null)
and
create table dbo.menu(mealID tinyint identity(1,1) primary key,antipasti tinyint,primi tinyint,secondi tinyint,dolci tinyint)
After adding some data, the contents of dbo.menu look something like:
mealID antipasti primi secondi dolci
------ --------- ----- ------- -----
1      1         5     9       13
2      2         6     10      14
3      3         7     11      15
4      4         8     12      16

And that's nice, but its not very usable by a human being. What I'd really like to get is:

mealID antipasti                      primi                          secondi                        dolci
------ ------------------------------ ------------------------------ ------------------------------ ------------------------------
1      Crostini                       Ravioli Nudi di Pesce          Pastello di Pesce              Granita
2      Prosciutto e meloni            Risotto alla Milanese          Ossobuco                       Timballo di Pere
3      Carpaccio                      Stracciatella                  Saltimbocca                    Castagnaccio
4      Polenta Fritta                 Trippa alla Fiorentina         Bollito Misto                  Zabaione

But how do you do that? In SQL Server 2005, a couple of new operators make this pretty easy: UNPIVOT and PIVOT. But how and why? Let's consider our matrix could also be represented as a list of paired values:

course     itemID
---------- ------
antipasti  1
primi      5
secondi    9
dolci      13
antipasti  2
primi      6
secondi    10
dolci      14
antipasti  3
primi      7
secondi    11
dolci      15
antipasti  4
primi      8
secondi    12
dolci      16

The unpivot operator makes that's easy to do:

select u.menuID,itemID from dbo.menu m unpivot (itemID for menuID in (antipasti,primi,secondi,dolci)) as u
And it makes joining the dishes in that list back to the table of dishes (dbo.MenuItems) rather easy: select u.menuID,i.name from dbo.menu m unpivot (itemID for menuID in (antipasti,primi,secondi,dolci)) as u join dbo.menuItems i on u.itemID = i.itemID So while that's cool, we're still dealing with a pair-list, not a matrix. Now, I might be a white guy that can't jump, but I certainly can PIVOT back into the matrix.
;with menus as (select mealID,u.menuID,i.name from dbo.menu m unpivot (itemID for menuID in (antipasti,primi,secondi,dolci)) as u join dbo.menuItems i on u.itemID = i.itemID) select * from menus pivot(max(name) for menuID in ([antipasti],[primi],[secondi],[dolci])) as p
Take that, Coach!

posted Wednesday, September 13, 2006 5:05 PM by ktegels




Powered by Dot Net Junkies, by Telligent Systems