<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Report Writing</title>
        <link>http://weblogs.sqlteam.com/jeffs/category/238.aspx</link>
        <description>Reporting Services, Crystal Reports, Access and other report-writing tools.  Also, this covers T-SQL techniques that come in especially handy in report-writing.</description>
        <language>en-US</language>
        <copyright>Jeff Smith</copyright>
        <managingEditor>smith_jeffreyt@yahoo.com</managingEditor>
        <generator>Subtext Version 1.9.4.0</generator>
        <item>
            <title>UNPIVOT: Normalizing data on the fly</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx</link>
            <description>Everyone seems to want to &lt;a href="http://weblogs.sqlteam.com/jeffs/category/156.aspx"&gt;"pivot" or "cross tab"&lt;/a&gt; data, but knowing how to do the opposite is equally important.  In fact, I would argue that the skill of "unpivoting" data is more useful and more important and more relevant to a SQL programmer, since pivoting results in denormalized data, while unpivoting can transform non-normalized data into a normalized result set.  We all know that there's lots of bad databases designs out there, so this can be a handy technique to know.  &lt;br /&gt;
&lt;br /&gt;
Of course, even a well designed, fully normalized database can still benefit from "unpivoting" from time to time, so let's take a look at some common situations and some of the options we have to handle this at our disposal.  We will focus on some traditional SQL techniques to do this, and then take a close look at the &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;operator that was introduced with SQL Server 2005.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Example #1:  A Bad database design&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Let's start with a commonly bad table design, in which someone has decided to relate a client to multiple contacts by designing their client table like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: left; margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;create table Clients &lt;br /&gt;
(   &lt;br /&gt;
    clientID int primary key, &lt;br /&gt;
    clientName varchar(100), &lt;br /&gt;
    contact1 int, &lt;br /&gt;
    contact2 int, &lt;br /&gt;
    contact3 int, &lt;br /&gt;
    contact4 int&lt;br /&gt;
)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;insert into Clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 1,'ABC Corp',1,34,2,null union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 2,'DEF Foundation',6,2,8,9 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 3,'GHI Inc.',5,9,null,null union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 4,'XYZ Industries',24,null,6,null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;clientID    clientName           contact1    contact2    contact3    contact4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- -------------------- ----------- ----------- ----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           ABC Corp             1           34          2           NULL&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           DEF Foundation       6           2           8           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           GHI Inc.             5           9           NULL        NULL&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           XYZ Industries       24          NULL        6           NULL&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(4 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-style: italic;"&gt;(Note: For brevity, I am not including the contact table here, nor the foreign key constraints.  Of course, with this table design, it would probably be pretty unlikely to find such constraints in the database anyway)&lt;/span&gt;&lt;br style="font-style: italic;" /&gt;
&lt;br /&gt;
With this design, it is not very easy or efficient to get a count of all contacts for each client, or to find out which contacts are related to which clients.   One thing we can do, however is to "unpivot" this table in a query that returns 1 row per ClientID/ContactID combination.  With that result set, we can easily now reference the table as if it were normalized and we can get the information we need.&lt;br /&gt;
&lt;br /&gt;
One way to do is to use UNION ALL to return each row in the clients table 4 times, and each time return a different contactID column:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select clientID, contact1 as ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;where contact1 is not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select clientID, contact2 as ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;where contact2 is not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select clientID, contact3 as ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;where contact3 is not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select clientID, contact4 as ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;where contact4 is not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;clientID    ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           5&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           24&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           34&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           8&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(11 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
Another option is to CROSS JOIN the Clients table with a table or resultset that returns 4 rows, which also effectively returns each row in the clients table 4 times.  For each of the 4 values in the table we are cross joining, we grab a different contact column:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select *&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    select c.clientID,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;       case n.n when 1 then c.contact1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            when 2 then c.contact2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            when 3 then c.contact3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;            when 4 then c.contact4 end as ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    from&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        clients c&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    cross join&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;        (select 1 as n union all select 2 union all select 3 union all select 4) n&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;)    &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    x&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;where&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    x.ContactID is not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;clientID    ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           34&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           8&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           5&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           24&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(11 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New; font-style: italic;" /&gt;
&lt;/div&gt;
&lt;span style="font-style: italic;"&gt;(Note that you can use a permanent table of Numbers in your database instead of generating it on the fly with a UNION, as shown)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Finally, however, there is an even eaiser way to handle this: the &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;operator, new with SQL 2005.  &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;works very efficiently and really allows you to handle this exact situation quite easily:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select clientID, Contact.ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (ContactID for ContactNumber in (contact1, contact2,contact3,contact4)) as Contact&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;clientID    ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           34&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           8&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           5&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           24&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(11 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
Much shorter to write, and more efficient to execute as well.  &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Taking a Closer Look at UNPIVOT&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The UNPIVOT operator is tricky to get a feel for, however, so let's take a look at it.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;unpivot (ContactID for ContactNumber in (contact1, contact2,contact3,contact4)) &lt;span style="font-weight: bold; background-color: rgb(255, 255, 153);"&gt;as Contact&lt;/span&gt;&lt;/span&gt;&lt;br style="background-color: rgb(255, 255, 153);" /&gt;
&lt;/div&gt;
&lt;br style="background-color: rgb(255, 255, 153);" /&gt;
&lt;span style="background-color: rgb(255, 255, 153);"&gt; &lt;/span&gt;First, the "As Contact" at the end is just labeling the entire unpivot result set with an alias, just as you must alias a derived table.  Each column returned by the pivot operator can be referenced by the alias if necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;unpivot (&lt;span style="background-color: rgb(255, 255, 153);"&gt;ContactID&lt;/span&gt; for&lt;span style="font-weight: bold; font-family: Courier New;"&gt; &lt;/span&gt;ContactNumber &lt;span style="font-weight: bold; background-color: rgb(255, 255, 153);"&gt;in (contact1, contact2,contact3,contact4)&lt;/span&gt;) as Contact&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
The "ContactID for" part says that we want to return a column called "ContactID" for each unpivoted row.  The IN() list is the columns that we are unpivoting; the values in the 4 columns listed here will be assigned to the ContactID column in the result.  So, the first time a particular row is unpivoted, the value of the 'contact1' column is assigned to ContactID, the next time it is the 'contact2' column, then 'contact3', and then finally 'contact4'.  Then, the next row is processed and it all begins again.  &lt;br /&gt;
&lt;br /&gt;
Thus, because we are unpivoting 4 values, we know that the result of the unpivot will have 4 times as many rows as the source data.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;unpivot (ContactID &lt;span style="font-weight: bold; background-color: rgb(255, 255, 153);"&gt;for ContactNumber&lt;/span&gt; in (contact1, contact2,contact3,contact4)) as Contact&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
UNPIVOT returns an additional column as well, which contains the name of the column that was used to produce each unpivoted row.   Here, we have specified that to be called ContactNumber.  Note that we actually did not return ContactNumber in our example, be we can easily add that in so you can see how it works:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select clientID,&lt;span style="font-weight: bold;"&gt; Contact.ContactNumber,&lt;/span&gt; Contact.ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from clients&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (ContactID for ContactNumber in (contact1, contact2,contact3,contact4)) as Contact&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;clientID    ContactNumber           ContactID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- ----------------------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           contact1                1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           contact2                34&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           contact3                2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           contact1                6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           contact2                2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           contact3                8&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2           contact4                9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           contact1                5&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;3           contact2                9&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           contact1                24&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;4           contact3                6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(11 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
So, you can see that the code to write is very short, but a little difficult to grasp at first.  In the end, though, we are able to take a bad table design and easily "fix it", at least temporarily, so that we can query it using simple and standard SQL statements to get what we need.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Example #2:  Normalizing a Transaction Table&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here's another common example:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;create table Transactions&lt;br /&gt;
(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    TranDate datetime,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Account varchar(10),&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    BudgetAmount money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    ActualAmount money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    ProjectionAmount money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    primary key (TranDate, Account)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;go&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;insert into Transactions&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-01-01','0001',354,65,58 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-01-02','0001',14,65,34 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-01-03','0001',0,65,622 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-01-04','0001',9,32,84&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;go&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;TranDate                Account    BudgetAmount          ActualAmount          ProjectionAmount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- --------------------- --------------------- ---------------------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001       354.00                65.00                 58.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001       14.00                 65.00                 34.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001       0.00                  65.00                 622.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001       9.00                  32.00                 84.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(4 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice that we have different columns for Budget, Actual and Projection, which is not really a great database design.  Much better would be to break this data out so that we have a single 'Amount' column and a 'TransactionType' column that specifies the type of each transaction.  We can transform our Transactions tables into this format using UNION ALL:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select TranDate, Account, 'BudgetAmount' as Type, BudgetAmount as Amount from transactions&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select TranDate, Account, 'ActualAmount' as Type, ActualAmount as Amount from transactions&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select TranDate, Account, 'ProjectionAmount' as Type, ProjectionAmount as Amount from transactions&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;TranDate                Account    Type             Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- ---------------- ---------------------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001       BudgetAmount     354.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001       BudgetAmount     14.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001       BudgetAmount     0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001       BudgetAmount     9.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001       ActualAmount     65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001       ActualAmount     65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001       ActualAmount     65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001       ActualAmount     32.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001       ProjectionAmount 58.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001       ProjectionAmount 34.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001       ProjectionAmount 622.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001       ProjectionAmount 84.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(12 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Or, we can use the &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;operator to do the same much easier:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select TranDate, Account, Type, Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Transactions&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Amount for Type in (BudgetAmount, ActualAmount, ProjectionAmount)) as Amount&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;TranDate                Account   Type                     Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- --------- ------------------------ ---------------------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001      BudgetAmount             354.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001      ActualAmount             65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-01 00:00:00.000 0001      ProjectionAmount         58.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001      BudgetAmount             14.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001      ActualAmount             65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-02 00:00:00.000 0001      ProjectionAmount         34.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001      BudgetAmount             0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001      ActualAmount             65.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-03 00:00:00.000 0001      ProjectionAmount         622.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001      BudgetAmount             9.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001      ActualAmount             32.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-01-04 00:00:00.000 0001      ProjectionAmount         84.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(12 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Example #3: "Unsummarizing" Data&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For those who work with accounting systems, this example may be familiar to you.   Many times, Accounting systems have "summary" tables that roll up transactional data into a structure like this:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;create table AccountBalances&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    CompanyID int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    AccountID int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    TransactionTypeID int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Year int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period1 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period2 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period3 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period4 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period5 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period6 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period7 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period8 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period9 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period10 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period11 money,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Period12 money&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;insert into AccountBalances&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 1,1,1,2008,200,300,400,500,400,0,0,0,0,0,0,0 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 1,2,1,2008,100,100,100,100,100,100,100,0,0,0,0,0 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 1,3,1,2008,150,0,50,10,10,200,400,45,0,0,0,0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-style: italic;"&gt;(As before, let's not worry about those foreign key constraints)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
These tables are often calculated when transactions are posted, or periods are closed.   Typically, many reports pull from these tables because it is much more efficient than summarizing thousands or millions of transactions, and the data is already "cross-tabbed" the way most reporting tools would like to display it.&lt;br /&gt;
&lt;br /&gt;
We can take this summarized data and "unpivot" it so we can still access the summarized data, but now it will be in a normalized structure.  All it takes is a simple &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;like this:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select CompanyID, AccountID, TransactionTypeID, Year, substring(Period,7,2) as PeriodNo, Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from AccountBalances&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Amount for Period in (Period1,Period2,Period3,Period4,Period5,Period6,Period7,Period8,Period9,Period10,Period11,Period12)) as Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;CompanyID   AccountID   TransactionTypeID Year        PeriodNo Amount&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------- ----------- ----------------- ----------- -------- ---------------------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        1        200.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        2        300.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        3        400.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        4        500.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        5        400.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        6        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        7        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        8        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        9        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        10       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        11       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           1           1                 2008        12       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        1        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        2        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        3        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        4        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        5        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        6        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        7        100.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        8        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        9        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        10       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        11       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           2           1                 2008        12       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        1        150.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        2        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        3        50.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        4        10.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        5        10.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        6        200.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        7        400.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        8        45.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        9        0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        10       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        11       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;1           3           1                 2008        12       0.00&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(36 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
We can filter so that only periods with a non-zero amount are included, and we can SELECT FROM this result set and get the exact data we need for whatever date range we want without worrying which column the actual data is in.&lt;br /&gt;
&lt;br /&gt;
This can also be done with a CROSS JOIN or a UNION ALL, but with 12 values to pivot, those options become much longer to write and &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;appears to be the way to go in this case.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Example #4: Multiple unpivots&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Finally, let's consider a more complicated example.  Here, we have a table that stores games played between two teams, where one team is the &lt;span style="font-style: italic;"&gt;HomeTeam &lt;/span&gt;and the other is the &lt;span style="font-style: italic;"&gt;AwayTeam:&lt;/span&gt;&lt;br style="font-style: italic;" /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;create table Teams&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    TeamCode char(3) primary key not null,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    TeamName varchar(100) not null&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;create table Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    GameDate datetime,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    HomeTeam char(3) references Teams(TeamCode),&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    AwayTeam char(3) references Teams(TeamCode),&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    HomeScore int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    AwayScore int,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    primary key (GameDate, HomeTeam), &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    constraint pk2 unique (GameDate, AwayTeam),&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    check (HomeTeam &amp;lt;&amp;gt; AwayTeam)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;insert into Teams&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 'BOS','Boston Red Sox' union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select 'NYY','New York Yankees'&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;insert into Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-01','BOS','NYY',3,1 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-02','BOS','NYY',6,4 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-03','BOS','NYY',2,3 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-08','NYY','BOS',6,0 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-09','NYY','BOS',2,6 union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select '2008-04-10','NYY','BOS',1,10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                HomeTeam AwayTeam HomeScore   AwayScore&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- -------- -------- ----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 BOS      NYY      3           1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 BOS      NYY      6           4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 BOS      NYY      2           3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 NYY      BOS      6           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 NYY      BOS      2           6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 NYY      BOS      1           10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(6 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
That may or may not be the best possible design for the Games table, but it is a common way to do it.  With data in that form, if we want to get the total runs scored per team across all games, or get each teams won-loss record, we need to make two passes through the table. This can be done fairly easily and efficiently with a union:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    HomeTeam as TeamCode, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    'Home' as HomeOrAway, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    HomeScore as Score, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore &amp;gt; AwayScore then 1 else 0 end as Win,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore &amp;lt; AwayScore then 1 else 0 end as Loss,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore = AwayScore then 1 else 0 end as Tie&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;union all&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;select GameDate, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    AwayTeam as TeamCode, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    'Away' as HomeOrAway, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    AwayScore as Score, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore &amp;lt; AwayScore then 1 else 0 end as Win,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore &amp;gt; AwayScore then 1 else 0 end as Loss,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    case when HomeScore = AwayScore then 1 else 0 end as Tie&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                TeamCode HomeOrAway Score       Win         Loss        Tie&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- -------- ---------- ----------- ----------- ----------- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 BOS      Home       3           1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 BOS      Home       6           1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 BOS      Home       2           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 NYY      Home       6           1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 NYY      Home       2           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 NYY      Home       1           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 NYY      Away       1           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 NYY      Away       4           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 NYY      Away       3           1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 BOS      Away       0           0           1           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 BOS      Away       6           1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 BOS      Away       10          1           0           0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(12 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Now, how can we do this with &lt;span style="font-weight: bold;"&gt;UNPIVOT&lt;/span&gt;?  This example is a bit more complicated, because we are "unpivoting" not only the score, but also the TeamCode, and we are also calculating a few extra columns (Win, Loss and Tie).&lt;br /&gt;
&lt;br /&gt;
So, can we &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;more than 1 column?  Let's start simply and do things one at a time.  First, let's &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;just the TeamCode:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, HomeOrAway, Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway     Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- -------------- ----&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 HomeTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 AwayTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 HomeTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 AwayTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 HomeTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 AwayTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 HomeTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 AwayTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 HomeTeam       NYY&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 AwayTeam       BOS&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(12 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
OK, so far so good.  Now, how do we get the score for the team as well?  Let's add another &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;clause to the SELECT, this time for Score:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, HomeOrAway, Team, Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; font-weight: bold;"&gt;unpivot (Score for HomeOrAway in (HomeScore, AwayScore)) as Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;Msg 265, Level 16, State 1, Line 1&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(128, 0, 0);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;The column name "HomeOrAway" specified in the UNPIVOT operator conflicts with the existing column name in the UNPIVOT argument.&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(128, 0, 0);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;Msg 8156, Level 16, State 1, Line 1&lt;/span&gt;&lt;br style="font-family: Courier New; color: rgb(128, 0, 0);" /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;The column 'HomeOrAway' was specified multiple times for 'Score'.&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Hmmm. OK, we cannot specify the same column for both pivots.  That is just an alias specification, no big deal, so let's just alias it as "HomeOrAway2" :&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, HomeOrAway, Team, Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Score for &lt;span style="font-weight: bold;"&gt;HomeOrAway2 &lt;/span&gt;in (HomeScore, AwayScore)) as Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway Team Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- ---- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 HomeTeam   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 HomeTeam   BOS  4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 AwayTeam   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 AwayTeam   NYY  4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 HomeTeam   BOS  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 HomeTeam   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 AwayTeam   NYY  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 AwayTeam   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 HomeTeam   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 HomeTeam   NYY  0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 AwayTeam   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 AwayTeam   BOS  0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 HomeTeam   NYY  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 HomeTeam   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 AwayTeam   BOS  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 AwayTeam   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 HomeTeam   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 HomeTeam   NYY  10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 AwayTeam   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 AwayTeam   BOS  10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(24 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Holy schnikies, it works!  We can specify more than one &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;clause for the same SQL statement!  Who would have thunk it?&lt;br /&gt;
&lt;br /&gt;
Uh oh -- wait a second.  We have 24 results returned.  We should have only 12.  Something is not right here.  Remember when we aliased our second unpivot column as "HomeOrAway2"?  We did not return that anywhere in our results.  Let's add that in and take a look:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, HomeOrAway, HomeOrAway2, Team, Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Score for HomeOrAway2 in (HomeScore, AwayScore)) as Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway HomeOrAway2 Team Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- ----------- ---- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   HomeScore   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   AwayScore   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   HomeScore   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   AwayScore   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 HomeTeam   HomeScore   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 HomeTeam   AwayScore   BOS  4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 AwayTeam   HomeScore   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-02 00:00:00.000 AwayTeam   AwayScore   NYY  4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 HomeTeam   HomeScore   BOS  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 HomeTeam   AwayScore   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 AwayTeam   HomeScore   NYY  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-03 00:00:00.000 AwayTeam   AwayScore   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 HomeTeam   HomeScore   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 HomeTeam   AwayScore   NYY  0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 AwayTeam   HomeScore   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-08 00:00:00.000 AwayTeam   AwayScore   BOS  0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 HomeTeam   HomeScore   NYY  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 HomeTeam   AwayScore   NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 AwayTeam   HomeScore   BOS  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-09 00:00:00.000 AwayTeam   AwayScore   BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 HomeTeam   HomeScore   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 HomeTeam   AwayScore   NYY  10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 AwayTeam   HomeScore   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-10 00:00:00.000 AwayTeam   AwayScore   BOS  10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(24 row(s) affected)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Notice what is happening here. Without an UNPIVOT, we had 6 rows.  We added one UNPIVOT to pivot two values, and got 12 rows.  Then, we added another pivot, again with two values, and got back 24.  Looking at the results, we can see that the single game at '2008-04-01' was unpivoted into 4 rows.  So, while we can unpivot multiple times, &lt;span style="font-style: italic;"&gt;there is no relation between each UNPIVOT.  &lt;/span&gt;That is, notice there is no correlation between HomeOrAway and HomeOrAway2.  Let's look at just that first game:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway HomeOrAway2 Team Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- ----------- ---- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   HomeScore   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   AwayScore   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   HomeScore   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   AwayScore   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
Both scores, home and away, are specified for each team -- even if it is not their matching score.  What we really want is only these two lines:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway HomeOrAway2 Team Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;----------------------- ---------- ----------- ---- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 HomeTeam   HomeScore   BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; text-decoration: line-through;"&gt;2008-04-01 00:00:00.000 HomeTeam   AwayScore   BOS  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; text-decoration: line-through;"&gt;2008-04-01 00:00:00.000 AwayTeam   HomeScore   NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;2008-04-01 00:00:00.000 AwayTeam   AwayScore   NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
How can we get there?  Well, there's always a WHERE clause!  We can simply filter our result so that the Left 4 characters of HomeOrAway matches the left 4 characters of HomeOrAway2.  After all, there is nothing magical about these unpivoted columns, they are data just like anything else.&lt;br /&gt;
&lt;br /&gt;
So, we can now write:&lt;br /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, left(HomeOrAway,4) as HomeOrAway, Team, Score&lt;br /&gt;
from Games&lt;br /&gt;
unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;br /&gt;
unpivot (Score for HomeOrAway2 in (HomeScore, AwayScore)) as Score&lt;br /&gt;
where left(HomeOrAway,4) = left(HomeOrAway2,4)&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway Team Score&lt;br /&gt;
----------------------- ---------- ---- -----------&lt;br /&gt;
2008-04-01 00:00:00.000 Home       BOS  3&lt;br /&gt;
2008-04-01 00:00:00.000 Away       NYY  1&lt;br /&gt;
2008-04-02 00:00:00.000 Home       BOS  6&lt;br /&gt;
2008-04-02 00:00:00.000 Away       NYY  4&lt;br /&gt;
2008-04-03 00:00:00.000 Home       BOS  2&lt;br /&gt;
2008-04-03 00:00:00.000 Away       NYY  3&lt;br /&gt;
2008-04-08 00:00:00.000 Home       NYY  6&lt;br /&gt;
2008-04-08 00:00:00.000 Away       BOS  0&lt;br /&gt;
2008-04-09 00:00:00.000 Home       NYY  2&lt;br /&gt;
2008-04-09 00:00:00.000 Away       BOS  6&lt;br /&gt;
2008-04-10 00:00:00.000 Home       NYY  1&lt;br /&gt;
2008-04-10 00:00:00.000 Away       BOS  10&lt;br /&gt;
&lt;br /&gt;
(12 row(s) affected)&lt;br /&gt;
&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
Now we are back to 12 results returned, the Homes and Aways match up, and things look good!  Hey, we just pulled off 2 unpivots at once, not bad!  From here, we can add our Win, Loss and Tie calculations as well.  Note that we also have removed "HomeOrAway2" from the SELECT, since we don't need to see that column in our result.  Finally, we are returning only the left 4 characters of HomeTeam or AwayTeam, so that the word 'Home' or 'Away' is returned in the HomeOrAway column.&lt;br /&gt;
&lt;br /&gt;
This seems like quite a bit of work.  Is &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;really the way to go in this scenario?  Maybe not.  I have not done full performance testing of &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;versus the other options shown (this article is way too long as it is!) but as always you should fully test your options and decide which offers the best performance and code simplicity.&lt;br /&gt;
&lt;br /&gt;
Another option if you want to unpivot more than 1 column is to just use one &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;cause, but then use CASE expressions to return the values you need.  For example:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select GameDate, left(HomeOrAway,4) as HomeOrAway, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;    Team, &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; font-weight: bold;"&gt;    case when HomeOrAway='HomeTeam' then HomeScore else AwayScore end as Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Games&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;unpivot (Team for HomeOrAway in (HomeTeam, AwayTeam)) as Team&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;GameDate                HomeOrAway Team Score&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; ----------------------- ---------- ---- -----------&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-01 00:00:00.000 Home       BOS  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-01 00:00:00.000 Away       NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-02 00:00:00.000 Home       BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-02 00:00:00.000 Away       NYY  4&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-03 00:00:00.000 Home       BOS  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-03 00:00:00.000 Away       NYY  3&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-08 00:00:00.000 Home       NYY  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-08 00:00:00.000 Away       BOS  0&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-09 00:00:00.000 Home       NYY  2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-09 00:00:00.000 Away       BOS  6&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-10 00:00:00.000 Home       NYY  1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; 2008-04-10 00:00:00.000 Away       BOS  10&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; (12 row(s) affected)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
This is kind of a combination of using &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;and a CROSS JOIN; the &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;doubles-up the results returned just as a CROSS JOIN would, and we just use CASE to return the column that we need depending if the current row is a "HomeTeam" or an "AwayTeam" row.    This is a fairly good solution and is probably better than using multiple &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;clauses.  &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;is a really handy operator, but it can be tricky to use.  You can &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;more than 1 column at a time, but beware of how it works -- each &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;uses it's own "pivot values" and you may get many more results than you intend. Thus, you may need to add criteria to your SELECT to ensure that only the results you are looking for are returned.  Alternatively, you can use one &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;along with CASE expressions to achieve the same results.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;is great, but the main thing is that you are at the mercy of the column names; the naming conventions of the columns used becomes data, and that can really complicate things.   In general, we want to keep our object names and our data seperate, so keep that limitation in mind if you wish to employ &lt;span style="font-weight: bold;"&gt;UNPIVOT &lt;/span&gt;in your code.   In some cases, an old-school UNION ALL or CROSS JOIN may be a preferrable solution.&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60573.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx</guid>
            <pubDate>Wed, 23 Apr 2008 14:33:15 GMT</pubDate>
            <wfw:comment>http://weblogs.sqlteam.com/jeffs/comments/60573.aspx</wfw:comment>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx#feedback</comments>
            <slash:comments>11</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60573.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60573.aspx</trackback:ping>
        </item>
        <item>
            <title>The Mailbag: Referencing Assemblies in Reporting Services; some SQL help</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/60377.aspx</link>
            <description>As &lt;a href="http://en.wikipedia.org/wiki/David_Letterman" target="_blank"&gt;David Letterman&lt;/a&gt; would say, wake the kids, call the neighbors, it's time for &lt;a href="http://weblogs.sqlteam.com/jeffs/contact.aspx"&gt;The Mailbag!&lt;/a&gt;  Just some quickies today.&lt;br /&gt;
&lt;br /&gt;
Christopher writes:&lt;br /&gt;
&lt;br /&gt;
&lt;p style="font-family: Arial; margin-left: 40px; font-style: italic;"&gt;Greetings Jeff,&lt;br /&gt;
&lt;br /&gt;
First and foremost, great job with all of the blogs. I have a questions&lt;br /&gt;
that I cannot seem to get a straight answer for. I am working with SQL&lt;br /&gt;
Server Reporting Services (SSRS) and have the need to create VB&lt;br /&gt;
functions to customize the reports generated. For example, a setter/getter to&lt;br /&gt;
display information that would not be readily available from the&lt;br /&gt;
query. SSRS allows this type of custom Visual Basic code to reside in the&lt;br /&gt;
report itself, but since most of my code is across multiple reports, it&lt;br /&gt;
makes 0 sense to place the same code in each report. Do you know of a&lt;br /&gt;
way that I can create a "code library" so that there is one location for&lt;br /&gt;
all of the code and all of the reports can access it?&lt;br /&gt;
&lt;br /&gt;
Thank you very much for your time and effort.&lt;br /&gt;
&lt;br /&gt;
Sincerely,&lt;br /&gt;
Christopher McGraw&lt;/p&gt;
Chris, Here's all the information that you need:  &lt;a href="http://msdn2.microsoft.com/en-us/library/ms153561.aspx" target="_blank"&gt;Using Custom Assemblies with Reports&lt;/a&gt;  (from SQL Server 2005 Books On Line).  I can't really add much to it -- it explains everything in detail.&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;br /&gt;
&lt;/div&gt;
Traner writes:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px; font-family: Arial; font-style: italic;"&gt;
&lt;p&gt;I have two tables, table1's primary key is table2's foreign key.&lt;br /&gt;
Table2 has multiple dates that relate to table1.&lt;br /&gt;
&lt;br /&gt;
ie. &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;Table1  : Table2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;JOE      : 10/18/07&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;DAVE    : 11/14/07&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;JOE      : 11/27/08&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br /&gt;
I am trying to get highest date from table2 related to table1.  Do you&lt;br /&gt;
know how this can be accomplished.  Any assistance will be greatly&lt;br /&gt;
appreciated.&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
That really isn't the clearest way to convey your schema, but I think I know what you mean.   Let's assume that Table1 has two columns, ID and Name, and that table2 has 3 columns, ID, Date and Value.&lt;br /&gt;
&lt;br /&gt;
First, to get the highest date per ID, you simply use the MAX() aggregate function along with GROUP BY when selecting from Table2:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select ID, Max(Date) as MaxDate&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from Table2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;group by ID&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Be sure to read up and practice with GROUP BY and aggregate functions if you are not familiar with them -- they are very powerful and very fundamental to SQL. &lt;br /&gt;
&lt;br /&gt;
Now, you can select from Table1 and join to the above SQL statement in a derived table to return all rows from Table1 and the maximum date from table 2:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New; font-weight: bold;"&gt;select Table1.ID, Table1.&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-weight: bold;"&gt;Name, t2.MaxDate&lt;/span&gt;&lt;br style="font-weight: bold;" /&gt;
&lt;span style="font-weight: bold;"&gt;from Table1&lt;/span&gt;&lt;br style="font-weight: bold;" /&gt;
&lt;span style="font-weight: bold;"&gt;inner join &lt;/span&gt;&lt;br /&gt;
(  select ID, Max(Date) as MaxDate&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;   from Table2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;   group by ID&lt;br /&gt;
) t2 on Table1.ID = Table2.ID&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
As you can see, we have enclosed our previous SQL statement in parenthesis, and assigned it an alias ("t2" in this case), and we can join to it and select from it just like any other table.  So, we have simply selected from Table1 and joined to a summarized version of Table2 that only returns the maximum date per ID.&lt;br /&gt;
&lt;br /&gt;
Finally, notice that all we are returning from Table2 is the date; if there are other columns from Table2 that we wish to return (for example, the "Value" column), we must add &lt;span style="font-style: italic;"&gt;another &lt;/span&gt;join to Table2, that returns only the row with the maximum date per ID:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select &lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;Table1.&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;ID, &lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;Table1.&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;Name, t2.MaxDate, &lt;span style="font-weight: bold;"&gt;Table2.Value&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt; from Table1&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt; inner join &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt; (  select ID, Max(Date) as MaxDate&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;   from Table2&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;   group by ID&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt; ) t2 on Table1.ID = Table2.ID&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;inner join Table2 on t2.ID = Table2.ID and t2.MaxDate = t2.Date&lt;/span&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
Notice that the "on" clause indicates that we are joining on ID as you might expect, but also on MaxDate = Date, so that we only return the row in Table2 that has the maximum date per ID.&lt;br /&gt;
&lt;br /&gt;
If you are using SQL Server 2005, this can be done a little easier, with only one join, using the new Rank() function:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;select x.ID, x.Name, x.Date, x.Value&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;from&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;(&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;  select Table1.ID, Table1.Name, Table2.Date, Table2.Value,&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; font-weight: bold;"&gt;   rank() over (partion by Table1.ID order by Table2.Date DESC) as Rank&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;  from Table1&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;  inner join Table2 on Table1.ID = Table2.ID&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;) x&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New; font-weight: bold;"&gt;where x.Rank = 1&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
More on Rank() and partitions &lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/03/28/60146.aspx"&gt;here&lt;/a&gt;.  Hope this helps you out. &lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60377.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/60377.aspx</guid>
            <pubDate>Thu, 18 Oct 2007 16:19:54 GMT</pubDate>
            <wfw:comment>http://weblogs.sqlteam.com/jeffs/comments/60377.aspx</wfw:comment>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/60377.aspx#feedback</comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60377.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60377.aspx</trackback:ping>
        </item>
        <item>
            <title>Creating CSV strings in SQL: Should Concatenation and Formatting Be Done at the Database Layer?</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/10/09/csv-strings-database-or-presentation.aspx</link>
            <description>A question I see very often in the SQLTeam forums is how to return data in a summarized form by concatenating a list of values into a single CSV column.  This can be done fairly easily in T-SQL, but as the formatting and concatenation requirements becomes more elaborate, be sure to ask yourself: Am I forcing presentation code into the database layer?  &lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/10/09/csv-strings-database-or-presentation.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60359.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/10/09/csv-strings-database-or-presentation.aspx</guid>
            <pubDate>Tue, 09 Oct 2007 19:02:57 GMT</pubDate>
            <wfw:comment>http://weblogs.sqlteam.com/jeffs/comments/60359.aspx</wfw:comment>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/10/09/csv-strings-database-or-presentation.aspx#feedback</comments>
            <slash:comments>18</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60359.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60359.aspx</trackback:ping>
        </item>
        <item>
            <title>Filter by month (plus other time periods)</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/09/14/sql-filter-by-month.aspx</link>
            <description>&lt;span style="font-weight: bold;"&gt;Introduction&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;Previously, &lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/09/10/group-by-month-sql.aspx"&gt;I wrote about grouping transactions by month&lt;/a&gt;.  Another common area of difficulty or confusion for SQL beginners is how to efficiently retrieve data just for a single month.&lt;br /&gt;
&lt;br /&gt;
There are two parts to this equation: First, what is the best way to declare parameters that will be used to indicate which month you are looking for?  Second, how can we efficiently and easily make use of those parameters to get back the data we need?&lt;br /&gt;
&lt;br /&gt;
Let's take a look at some approaches, both &lt;span style="color: rgb(0, 102, 0);"&gt;recommended &lt;/span&gt;and &lt;span style="color: rgb(128, 0, 0);"&gt;not&lt;/span&gt;.  &lt;br /&gt;
&lt;br /&gt;
And, please: if you are not using the DATETIME data type to store dates in your tables, don't even bother reading further -- fix your design first!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Month Parameter Options &lt;/span&gt;&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt; &lt;br /&gt;
&lt;br /&gt;
@YearMonth as char(6)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
If you know me at all, you know that I will advise not to use this approach.  We’ll need to parse and validate the values passed into ensure that they are valid, and we need to somehow communicate exactly which format to use when setting the parameter values. For example, is it “MM-YY”, or “MMYYYY”, or “MM/YY”, or “YYYYMM”, etc?  It simply makes no sense to introduce string formatting conventions and parsing and validating into the equation when you simply don’t need to.  Don’t do it.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 102, 0);"&gt; @Year as int, @Month as int&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This approach works fine, since now we have no string parsing or ambiguity to deal with. It is very clear that Year and Month are both simply numeric values.  We can do a quick check to ensure that are @Month value is between 1 and 12, and that our @Year value is within our desired range as well.&lt;br /&gt;
&lt;br /&gt;
As we will see later, an optimal solution will require finding the first day of the month requested.  How can we do that given a @Year and a @Month value?  Simple, you can either &lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx"&gt;use the Date function here&lt;/a&gt; and write:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;Declare @FirstDayOfMonth datetime&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; Set @FirstDayOfMonth = dbo.Date(@Year,@Month,1)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
… or you can apply the same logic using DateAdd() like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px; font-family: Courier New;"&gt;Declare @FirstDayOfMonth datetime&lt;br /&gt;
Set @FirstDayOfMonth = dateadd(month,((@Year-1900)*12)+@Month-1,0)&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Either way, the result is the same: for a given @Year and @Month, the first day of that month (at midnight) is returned.  If you aren’t sure how this formula works (or even if it will work at all), just test it out.&lt;br /&gt;
&lt;br style="color: rgb(51, 153, 102);" /&gt;
&lt;span style="color: rgb(0, 102, 0); font-family: Courier New;"&gt; @DateInMonth as datetime&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here, we can simply accept any datetime value, and use the year and month of that date to indicate which month should be returned.  A user can pass in the first day of the month, the last day, or any day in between – it doesn’t matter.  This works well because we know the parameter will be a valid date, and we can quickly and simply get the year/month of the @DateInMonth parameter using the Year() and Month() functions:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;Declare @Year int, @Month int&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; Select @Year = Year(@DateInMonth), @Month = Month(@DateInMonth)&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;/div&gt;
&lt;br /&gt;
We can also get the first day of the month for a given @DateInMonth quite easily, using another DateAdd() trick:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;Declare @FirstDayOfMonth&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; Set @FirstDayOfMonth = DateAdd(month, DateDiff(month,0, @DateInMonth), 0)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
So, accepting a dateTime parameter to indicate which month you are after is also a good technique to use.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;WHERE Clause Options &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the @Year, @Month and @FirstDayOfMonth values ready to go, we must decide how to use these values to write our query.   Here are some options (again, both &lt;span style="color: rgb(0, 102, 0);"&gt;good &lt;/span&gt;and &lt;span style="color: rgb(128, 0, 0);"&gt;bad&lt;/span&gt;):&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt; where Year(TranDate) =@Year and Month(TranDate) = @Month&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This approach will work fine, but it will not be able to use any indexes that might exist on your TranDate column.  Thus, it will not be as efficient as possible.  Every single TranDate value must be retrieved from your table, the Year() and Month() formulas must be applied, and then the results must be tested to determine if that row should be returned or not.    Overall, avoid wrapping indexable columns in functions such as these in your criteria.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt; where convert(varchar(6), TranDate, 112) = convert(varchar(6), @FirstDayOfMonth) &lt;/span&gt;&lt;br /&gt;
-- or --&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;where convert(varchar(6), TranDate, 112) = left(@Year,4)+right('0' + left(@Month,2),2)&lt;br /&gt;
&lt;/span&gt; -- or --&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt;where convert(varchar(6), TranDate, 112) = @YearMonth&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
These WHERE clauses all convert the TranDate to a VARCHAR in the format of YYYMMDD, but truncated at 6 characters, resulting in a YYYMM formatted string.  Then, using different methods, that string is compared to a YYYYMM representation of the month we'd like to return.  This is a bad approach to take because it requires that every TranDate be converted to a string in order to filter the rows, thus no indexes can be used.  Using any conversions or string manipulations to filter data when better options exist is never the way to go.   At worst, it is also very confusing to work with since it can be unclear exactly what some of these convert() functions and string expressions are doing.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(128, 0, 0);"&gt; where TranDate between @FirstDayOfMonth and @LastDayOfMonth&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
What if we calculate, for a given @Year and @Month, the first and last day of the month, store them in variables, and then use that range for our criteria?  This will let us use indexes, it will be clear and concise, and it makes good sense.&lt;br /&gt;
&lt;br /&gt;
However, there is a minor flaw in this logic:  Suppose @Year is 2006, and @Month is 1. If we set @LastDayOfMonth to ‘2006-01-31 12:00:00 AM’, any transactions after 12:00:00 AM on the last day of the month will not be included!  We could calculate the very last 1/300th of a millisecond on the last day of the month to use as our upper limit, but there is an even easier way ...&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; color: rgb(0, 102, 0);"&gt; where TranDate &amp;gt;= @FirstDayOfMonth and TranDate &amp;lt; @FirstDayOfNextMonth&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here, we won’t have any issues with times other than midnight leading to missed transactions.&lt;br /&gt;
&lt;br /&gt;
We already have the @FirstDayOfMonth, all we need is the @FirstDayOfNextMonth.  That is easily obtained by using DateAdd() to add one month to the @FirstDayOfMonth, as shown:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt;Declare @FirstDayOfNextMonth&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; Set @FirstDayOfNextMonth = DateAdd(month, @FirstDayOfMonth,1)&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
With that, we are all set!  Indexes can be used and any datetime value within our range will be properly selected.  I highly recommend using this approach whenever you need to select dates for a single month; there is no need to force date computations upon all values in your table when a simple range is all you need.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;Other Time Periods&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;The same approach can be applied if you need to allow for a range of months to be specified, not just a single month.  Simply calculate the first day of the&lt;span style="font-style: italic;"&gt; starting &lt;/span&gt;month, and then calculate the first day of the month &lt;span style="font-style: italic;"&gt;after &lt;/span&gt;the &lt;span style="font-style: italic;"&gt;ending &lt;/span&gt;month.  Then, you can use that date range to filter your data as shown above.  &lt;br /&gt;
&lt;br /&gt;
You should also follow these same guidelines if you'd like to filter data by a specified year, quarter, or week.  "Year-to-date" filtering will also work the exact same way.&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;
Conclusion &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
At the end of the day, accomplishing our task is very simple:&lt;br /&gt;
&lt;br /&gt;
1.    Accept either @Year and @Month parameters or a single @DateInMonth parameter to indicate which month should be returned&lt;br /&gt;
2.    Calculate the @FirstDayOfMonth and the @FirstDayOfNextMonth using those parameters&lt;br /&gt;
3.    Select your rows with a WHERE clause that returns transaction dates equal to or greater than @FirstDayOfMonth, and less than @FirstDayOfNextMonth, to ensure that all dates at the end of your range are captured and that indexes can be used.&lt;br /&gt;
&lt;br /&gt;
Good luck, and remember: Declare your parameters to be clear and precise, and write your WHERE clauses to be as efficient and accurate as possible.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;see also:&lt;br /&gt;
&lt;/span&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/10/15/time-spans-durations-sql-server.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl08_HyperLink1"&gt; Working with Time Spans and Durations in SQL Server&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/09/10/group-by-month-sql.aspx" title="View Entry"&gt;Group by Month (and other time periods)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/08/29/SQL-Dates-and-Times.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl08_HyperLink1"&gt;Working with Date and/or Time values in SQL Server: Don't Format, Don't Convert -- just use DATETIME&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/07/03/60248.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl10_HyperLink1"&gt;Data Types -- The Easiest Part of Database Design&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/04/13/format-date-sql-server.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl06_HyperLink1"&gt;How to format a Date or DateTime in SQL Server&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2004/12/02/2954.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl06_HyperLink1"&gt;Breaking apart the DateTime datatype -- Separating Dates from Times in your Tables&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/10/31/sql-server-2005-date-time-only-data-types.aspx" title="View Entry" id="ctl00_pageContent_Editor_Results_rprSelectionList_ctl04_HyperLink1"&gt;Date Only and Time Only data types in SQL Server 2005 (without the CLR)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="../../../../jeffs/archive/2007/01/02/56079.aspx" title="View Entry"&gt;Essential SQL Server Date, Time and DateTime Functions&lt;/a&gt; 				 				&lt;/li&gt;
&lt;/ul&gt;
&lt;/span&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60326.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/09/14/sql-filter-by-month.aspx</guid>
            <pubDate>Fri, 14 Sep 2007 16:21:07 GMT</pubDate>
            <wfw:comment>http://weblogs.sqlteam.com/jeffs/comments/60326.aspx</wfw:comment>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/09/14/sql-filter-by-month.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60326.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60326.aspx</trackback:ping>
        </item>
        <item>
            <title>Thinking Set-Based .... or not?</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/04/30/60192.aspx</link>
            <description>So, I hear you're a "set-based SQL master" !  As Yoda once said, you've "unlearned what you have learned". You've trained yourself to attack your database code not from a procedural, step-by-step angle, but rather from the set-based "do it all at once" approach.  However, don't completely forget the most important skill that you learned in the procedural world!&lt;br&gt;&lt;br&gt;&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/04/30/60192.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60192.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/04/30/60192.aspx</guid>
            <pubDate>Mon, 30 Apr 2007 17:03:11 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/04/30/60192.aspx#feedback</comments>
            <slash:comments>18</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60192.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60192.aspx</trackback:ping>
        </item>
        <item>
            <title>Better Alternatives to a FULL OUTER JOIN </title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx</link>
            <description>As many of you know, I strongly recommend that you avoid using RIGHT OUTER JOINS, since they make your SQL code less readable and are easily rewritten as LEFT OUTER JOINs.  In addition, I have yet to find a situation where a FULL OUTER JOIN makes sense or is necessary -- I have found that in just about every case other techniques work better.&lt;br&gt;&lt;br&gt;&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60178.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx</guid>
            <pubDate>Thu, 19 Apr 2007 15:56:34 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx#feedback</comments>
            <slash:comments>45</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60178.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60178.aspx</trackback:ping>
        </item>
        <item>
            <title>How to be an Effective Report Writer</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/04/13/How-to-be-an-Effective-Report-Writer.aspx</link>
            <description>A non-technical guide to writing reports, with a focus on  managing requirements, results, and expectations.&lt;br&gt;&lt;br&gt;
&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/04/13/How-to-be-an-Effective-Report-Writer.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60173.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/04/13/How-to-be-an-Effective-Report-Writer.aspx</guid>
            <pubDate>Fri, 13 Apr 2007 15:03:18 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/04/13/How-to-be-an-Effective-Report-Writer.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60173.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60173.aspx</trackback:ping>
        </item>
        <item>
            <title>Conditional Joins in SQL Server</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2007/04/03/Conditional-Joins.aspx</link>
            <description>Sometimes, when writing SELECTs, we come across situations in which we we need to write a join containing a &lt;b&gt;condition&lt;/b&gt; of some sort.  You might think to do this with either a CASE expression or with some OR boolean logic in your join expression.  There's a much better way to approach the problem.
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2007/04/03/Conditional-Joins.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/60160.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2007/04/03/Conditional-Joins.aspx</guid>
            <pubDate>Tue, 03 Apr 2007 16:15:47 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2007/04/03/Conditional-Joins.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/60160.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/60160.aspx</trackback:ping>
        </item>
        <item>
            <title>Rendering Excel and Word files with SQL Server</title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2006/07/18/10649.aspx</link>
            <description>I've been playing around with a handy tool for creating Word and Excel files called OfficeWriter that's pretty impressive.
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2006/07/18/10649.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/10649.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2006/07/18/10649.aspx</guid>
            <pubDate>Tue, 18 Jul 2006 19:05:00 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2006/07/18/10649.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/10649.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/10649.aspx</trackback:ping>
        </item>
        <item>
            <title>.NET CrossTabs versus SQL Server CrossTabs </title>
            <link>http://weblogs.sqlteam.com/jeffs/archive/2005/05/12/5127.aspx</link>
            <description>As promised in my last post, here is some performance testing to help you determine the performance benefits (if any) of performing your crosstabs at the presentation or code layer, as opposed to forcing SQL Server to do this.
&lt;br&gt;&lt;br&gt;
&lt;a href="http://weblogs.sqlteam.com/jeffs/archive/2005/05/12/5127.aspx"&gt;read more...&lt;/a&gt;&lt;img src="http://weblogs.sqlteam.com/jeffs/aggbug/5127.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Jeff Smith</dc:creator>
            <guid>http://weblogs.sqlteam.com/jeffs/archive/2005/05/12/5127.aspx</guid>
            <pubDate>Thu, 12 May 2005 14:01:00 GMT</pubDate>
            <comments>http://weblogs.sqlteam.com/jeffs/archive/2005/05/12/5127.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://weblogs.sqlteam.com/jeffs/comments/commentRss/5127.aspx</wfw:commentRss>
            <trackback:ping>http://weblogs.sqlteam.com/jeffs/services/trackbacks/5127.aspx</trackback:ping>
        </item>
    </channel>
</rss>