views:

29

answers:

1

HI, Using SQL server 2005 I have the following query:

SELECT 
contact_id      
,YEAR(date_created)         AS giftyear
,SUM(amount_exc_vat)        AS year_total_xGA
,SUM(amount_inc_vat)        AS year_total_inGA
,COUNT(*) AS numGifts 
FROM gifts 
GROUP BY contact_id 
,Year(date_created)

Which returns data that looks like this:

contact_id  |  giftyear  | year_total_xVAT  |year_total_inVAT  |  numGifts
id001      |    2006    |   17.00          |      21.79       |     4
id001      |    2007    |   5.00           |    6.41          |     1
id001       |   2008    |   5.00           |       6.41       |     1

I then want to pivot this data to have the table looking like this instead

contact_id  |  gift_2006  |  2006_excVAT  | 2006_incVAT  | 2007gifts | 2007_excVAT  |  2007_incVAT | gift_2008  |  2008_excvat  |  2008_incvat
id001       |    1        |     17.00     |    21.79     |  1        |    5.00      |  6.41         |    1       |    5.00       |    6.41

So where gift_2006 etc is essentially a CASE statement saying if the contact_id gave a gift in 2006 then assign 1 else 0 - so that for one contact all of the information is contained in one row

Thanks in advance :)

+2  A: 
SELECT 
contact_id,   
 CASE WHEN COUNT(CASE WHEN YEAR(date_created) = 2006 THEN 1 END) > 0 THEN 1 ELSE 0 END AS gift_2006,
SUM(CASE WHEN YEAR(date_created) = 2006 THEN amount_exc_vat END) AS [2006_excVAT] ,
SUM(CASE WHEN YEAR(date_created) = 2006 THEN amount_inc_vat END) AS [2006_incVAT] ,
CASE WHEN COUNT(CASE WHEN YEAR(date_created) = 2007 THEN 1 END) > 0 THEN 1 ELSE 0 END AS gift_2007,
SUM(CASE WHEN YEAR(date_created) = 2007 THEN amount_exc_vat END) AS [2007_excVAT] ,
SUM(CASE WHEN YEAR(date_created) = 2007 THEN amount_inc_vat END) AS [2007_incVAT] ,
CASE WHEN COUNT(CASE WHEN YEAR(date_created) = 2008 THEN 1 END) > 0 THEN 1 ELSE 0 END AS gift_2008,
SUM(CASE WHEN YEAR(date_created) = 2008 THEN amount_exc_vat END) AS [2008_excVAT] ,
SUM(CASE WHEN YEAR(date_created) = 2008 THEN amount_inc_vat END) AS [2008_incVAT] 
FROM gifts 
GROUP BY contact_id 
Martin Smith
When I try this I get the error saying that date_created is not included as part of the aggregation, and when I add it in it produces duplicate rows for each contact_id. Also I've heard from some poeple that CASE statements are the most efficient, would having all of these nested CASE statements slow things down a lot? - Thanks,
Davin
@Davin - Well that's the basic idea. As you didn't provide any DDL (create table statements) in your post I didn't test it this end. If you edit your question to include the create table script for gifts I will do. This is the only reasonable way of doing it. The `Pivot` operator is basically syntactic sugar for this approach.
Martin Smith
By the way I did just test it this end and didn't get any such error at all. Are you sure you haven't changed anything?
Martin Smith
The only thing I changed was to add in 2 additional CASE statements for the years 2009 / 2010, but apart from that it was all the same as what you entered above?
Davin
@Davin - Can you try my answer exactly as written and confirm it works.
Martin Smith
@Martin - found an error in the database which is now amended and this works perfectly so thanks for all your help - just suprised that it ended up being a series of case statement that fit the bill! :)
Davin
@Davin - It's basically I/O which determines the efficiency of queries. This does it with one pass through the data so can't really be improved upon.
Martin Smith
@ Martin - why do the case statements relating to VAT all need to end with the column name in []? It's just that I'm trying to put the results into a temporary table and it doesn't seem to like that!
Davin
@Davin - Because the column name doesn't meet the standard rules for identifiers in that they start with a digit. You should be able to just do `SELECT ... INTO #temptable FROM ...` though.
Martin Smith
@Martin, thanks again - seems such a simple fix now!!! :)
Davin