Imagine a table (called test1) with monthly sales numbers
year | month | SalesPerson | Sales $ |
2009 | 6 | a | 6.1 |
2009 | 6 | b | 6.2 |
2009 | 7 | a | 7.1 |
2009 | 8 | a | 8.1 |
2009 | 8 | b | 8.2 |
2009 | 9 | b | 9.2 |
2010 | 1 | a | 1.1 |
2010 | 2 | b | 2.1 |
2010 | 3 | b | 3.1 |
2010 | 4 | a | 4.1 |
2010 | 4 | b | 4.2 |
2010 | 5 | a | 5.1 |
You can create and populate your test table using this SQL (works for Sybase and MS SQL server):
/***********************************************************/ if exists (select 1 from sysobjects where name='test1' and type='U') begin drop table test1 end go create table test1 ( year int, month int, sales_team char(4), sales float ) insert test1 select 2009, 6, "a", 6.1 insert test1 select 2009, 6, "b", 6.2 insert test1 select 2009, 7, "a", 7.1 insert test1 select 2009, 8, "a", 8.1 insert test1 select 2009, 8, "b", 8.2 insert test1 select 2009, 9, "b", 9.1 insert test1 select 2010, 1, "a", 1.1 insert test1 select 2010, 2, "b", 2.1 insert test1 select 2010, 3, "b", 3.1 insert test1 select 2010, 4, "a", 4.1 insert test1 select 2010, 4, "b", 4.2 insert test1 select 2010, 5, "b", 5.1 go /*******************************************************************/
Let's say we need to sum-up the sales numbers by months for each year in one SQL statement. Below are the 2 ways of achieving that using one SQL statement.
The recommended way (and enforced by Microsoft in their SQL Server) is to use the case statement with GROUP BY as follows:
/********************************************************/ select year, m_1_sls = sum(case when month=1 then sales else null end), m_2_sls = sum(case when month=2 then sales else null end), m_3_sls = sum(case when month=3 then sales else null end), m_4_sls = sum(case when month=4 then sales else null end), m_5_sls = sum(case when month=5 then sales else null end), m_6_sls = sum(case when month=6 then sales else null end), m_7_sls = sum(case when month=7 then sales else null end), m_8_sls = sum(case when month=8 then sales else null end), m_9_sls = sum(case when month=9 then sales else null end), m_10_sls = sum(case when month=10 then sales else null end), m_11_sls = sum(case when month=11 then sales else null end), m_12_sls = sum(case when month=12 then sales else null end) from test1 group by year /****************************************************/
There is also less conventional way of achieving pretty much the same result - using "characteristic functions" as suggested by Anatoly Abramovich, Eugene Birger, and David Rozenshtein
/***********************************************************/ SELECT year, m_1_sls=sum( (1- ABS( SIGN( ISNULL( 1 - month, 1)))) * sales ), m_2_sls=sum( (1- ABS( SIGN( ISNULL( 2 - month, 1)))) * sales ), m_3_sls=sum( (1- ABS( SIGN( ISNULL( 3 - month, 1)))) * sales ), m_4_sls=sum( (1- ABS( SIGN( ISNULL( 4 - month, 1)))) * sales ), m_5_sls=sum( (1- ABS( SIGN( ISNULL( 5 - month, 1)))) * sales ), m_6_sls=sum( (1- ABS( SIGN( ISNULL( 6 - month, 1)))) * sales ), m_7_sls=sum( (1- ABS( SIGN( ISNULL( 7 - month, 1)))) * sales ), m_8_sls=sum( (1- ABS( SIGN( ISNULL( 8 - month, 1)))) * sales ), m_9_sls=sum( (1- ABS( SIGN( ISNULL( 9 - month, 1)))) * sales ), m_10_sls=sum( (1- ABS( SIGN( ISNULL( 10 - month, 1)))) * sales ), m_11_sls=sum( (1- ABS( SIGN( ISNULL( 11 - month, 1)))) * sales ), m_12_sls=sum( (1- ABS( SIGN( ISNULL( 12 - month, 1)))) * sales ) from test1 group by year /****************************************************/The result of these SQLs will be:
year | m_1_sls | m_2_sls | m_3_sls | m_4_sls | m_5_sls | m_6_sls | m_7_sls | m_8_sls | m_9_sls | m_10_sls | m_11_sls | m_12_sls |
2009 | null | null | null | null | null | 12.3 | 7.1 | 16.3 | 9.1 | null | null | null |
2010 | 1.1 | 2.1 | 3.1 | 8.3 | 5.1 | null | null | null | null | null | null | null |