/* Advanced SQL Programming			      Fall 2002 */
/*		Grouping and aggregate functions		*/
/*								*/
1> use pubs2
2> go
/*								*/
/* Find maximum advance and number of titles for each publisher.*/
/*								*/
1> select pub_id, count(*), max(advance)
2> from titles
3> group by pub_id
4> go
 pub_id                                      
 ------ ----------- ------------------------ 
 0736             5                10,125.00 
 0877             7                15,000.00 
 1389             6                 8,000.00 

(3 rows affected)
/*								*/
/* Break down by type without grouping?				*/
/*								*/
1>  select pub_id, type, count(*), max(advance)
2> from titles
3> group by pub_id
4> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 1389   business               6                 8,000.00 
 1389   business               6                 8,000.00 
 0736   business               5                10,125.00 
 1389   business               6                 8,000.00 
 0877   mod_cook               7                15,000.00 
 0877   mod_cook               7                15,000.00 
 0877   UNDECIDED              7                15,000.00 
 1389   popular_comp           6                 8,000.00 
 1389   popular_comp           6                 8,000.00 
 1389   popular_comp           6                 8,000.00 
 0877   psychology             7                15,000.00 
 0736   psychology             5                10,125.00 
 0736   psychology             5                10,125.00 
 0736   psychology             5                10,125.00 
 0736   psychology             5                10,125.00 
 0877   trad_cook              7                15,000.00 
 0877   trad_cook              7                15,000.00 
 0877   trad_cook              7                15,000.00 

(18 rows affected)
/*								*/
/*  Can we fix the problem using distinct?                   	*/
/*								*/
1> select distinct pub_id, type, count(*), max(advance)
2> from titles
3> group by pub_id
4> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 0877   UNDECIDED              7                15,000.00 
 0736   business               5                10,125.00 
 1389   business               6                 8,000.00 
 0877   mod_cook               7                15,000.00 
 1389   popular_comp           6                 8,000.00 
 0736   psychology             5                10,125.00 
 0877   psychology             7                15,000.00 
 0877   trad_cook              7                15,000.00 

(8 rows affected)
/*								*/
/*  Notice that the count cannot be right in results above - 	*/
/*  we know there are only 18 titles in the database.		*/
/*  Must group at least by all columns not in the aggregate	*/
/*  function calculation:					*/
/*								*/
1> select pub_id, type, count(*), max(advance)
2> from titles
3> group by pub_id, type
4> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 0736   business               1                10,125.00 
 0736   psychology             4                 6,000.00 
 0877   UNDECIDED              1                     NULL 
 0877   mod_cook               2                15,000.00 
 0877   psychology             1                 7,000.00 
 0877   trad_cook              3                 8,000.00 
 1389   business               3                 5,000.00 
 1389   popular_comp           3                 8,000.00 

(8 rows affected)
/*								*/
/*  Groups only work when groups actually exist across rows -	*/
/*  if price added to previous grouping, only two titles	*/
/*  in one of the publisher/type groups have the same price.	*/
/*								*/
1> select pub_id, type, price, count(*), max(advance)
2> from titles
3> group by pub_id, type, price
4> go
 pub_id type         price                               
	                          
 ------ ------------ ------------------------ ----------- 
	------------------------ 
 0736   business                         2.99           1
	                10,125.00 
 0736   psychology                       7.00           1
	                 6,000.00 
 0736   psychology                       7.99           1
	                 4,000.00 
 0736   psychology                      10.95           1
	                 2,275.00 
 0736   psychology                      19.99           1
	                 2,000.00 
 0877   UNDECIDED                        NULL           1
	                     NULL 
 0877   mod_cook                         2.99           1
	                15,000.00 
 0877   mod_cook                        19.99           1
	                     0.00 
 0877   psychology                      21.59           1
	                 7,000.00 
 0877   trad_cook                       11.95           1
	                 4,000.00 
 0877   trad_cook                       14.99           1
	                 8,000.00 
 0877   trad_cook                       20.95           1
	                 7,000.00 
 1389   business                        11.95           1
	                 5,000.00 
 1389   business                        19.99           2
	                 5,000.00 
 1389   popular_comp                     NULL           1
	                     NULL 
 1389   popular_comp                    20.00           1
	                 8,000.00 
 1389   popular_comp                    22.95           1
	                 7,000.00 

(17 rows affected)
/*								*/
/*  Examples to show difference between where and having	*/
/*  Find count and advance for titles with price > $10.		*/
/*								*/
/*  Use where to narrow down selection before grouping.		*/
/*								*/
1> select pub_id, type, count(*), max(advance)
2> from titles
3> where price > 10
4> group by pub_id, type
5> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 0736   psychology             2                 2,275.00 
 0877   mod_cook               1                     0.00 
 0877   psychology             1                 7,000.00 
 0877   trad_cook              3                 8,000.00 
 1389   business               3                 5,000.00 
 1389   popular_comp           2                 8,000.00 

(6 rows affected)
/*								*/
/*  Use having (with distinct if necessary) to set condition	*/
/*  after grouping and calculating.				*/
/*								*/
1> select pub_id, type, count(*), max(advance)
2> from titles
3> group by pub_id, type
4> having price > 10
5> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 1389   business               3                 5,000.00 
 1389   business               3                 5,000.00 
 1389   business               3                 5,000.00 
 0877   mod_cook               2                15,000.00 
 1389   popular_comp           3                 8,000.00 
 1389   popular_comp           3                 8,000.00 
 0877   psychology             1                 7,000.00 
 0736   psychology             4                 6,000.00 
 0736   psychology             4                 6,000.00 
 0877   trad_cook              3                 8,000.00 
 0877   trad_cook              3                 8,000.00 
 0877   trad_cook              3                 8,000.00 

(12 rows affected)
1> select distinct pub_id, type, count(*), max(advance)
2> from titles
3> group by pub_id, type
4> having price > 10
5> go
 pub_id type                                              
 ------ ------------ ----------- ------------------------ 
 1389   business               3                 5,000.00 
 0877   mod_cook               2                15,000.00 
 1389   popular_comp           3                 8,000.00 
 0877   psychology             1                 7,000.00 
 0736   psychology             4                 6,000.00 
 0877   trad_cook              3                 8,000.00 

(6 rows affected)
/*								*/
/*  Example using datetime as basis for grouping - in what 	*/
/*  month are most titles published?				*/
/*  Look at data first:						*/
/*								*/
1> select title_id, pubdate from titles
2> go
 title_id pubdate                    
 -------- -------------------------- 
 BU1032          Jun 12 1986 12:00AM 
 BU1111          Jun  9 1988 12:00AM 
 BU2075          Jun 30 1985 12:00AM 
 BU7832          Jun 22 1987 12:00AM 
 MC2222          Jun  9 1989 12:00AM 
 MC3021          Jun 18 1985 12:00AM 
 MC3026          Sep 15 1999  2:26PM 
 PC1035          Jun 30 1986 12:00AM 
 PC8888          Jun 12 1987 12:00AM 
 PC9999          Sep 15 1999  2:26PM 
 PS1372          Oct 21 1990 12:00AM 
 PS2091          Jun 15 1989 12:00AM 
 PS2106          Oct  5 1990 12:00AM 
 PS3333          Jun 12 1988 12:00AM 
 PS7777          Jun 12 1988 12:00AM 
 TC3218          Oct 21 1990 12:00AM 
 TC4203          Jun 12 1985 12:00AM 
 TC7777          Jun 12 1987 12:00AM 

(18 rows affected)
1> select datepart(mm, pubdate) Month, count(*) NumPublished
2> from titles
3> group by datepart(mm, pubdate)
4> go
                         
 Month	     NumPublished
 ----------- ----------- 
           6          13 
           9           2 
          10           3 

(3 rows affected)
/*								*/
/*  Note:  Cannot group by alias				*/
/*								*/
1> select datepart(mm, pubdate) Month, count(*)
2> from titles
3> group by Month
4> go
Msg 207, Level 16, State 2:
Line 1:
Invalid column name 'Month'.
/*								*/
/*  All aggregate functions except count remove nulls.		*/
/*  Example:  Find average advance two different ways.		*/
/*								*/
1> select advance from titles
2> go
 advance                  
 ------------------------ 
                 5,000.00 
                 5,000.00 
                10,125.00 
                 5,000.00 
                     0.00 
                15,000.00 
                     NULL 
                 7,000.00 
                 8,000.00 
                     NULL 
                 7,000.00 
                 2,275.00 
                 6,000.00 
                 2,000.00 
                 4,000.00 
                 7,000.00 
                 4,000.00 
                 8,000.00 

(18 rows affected)
/*  								*/
/*  Avg(advance) averages 16 non-null values (above)		*/
/*								*/
1> select  avg(advance) from titles
2> go
                          
 ------------------------ 
                 5,962.50 

(1 row affected)
/*								*/
/* Sum/count adds 16 non-null values, divides by all 18.	*/
/*								*/
1> select sum(advance)/count(*) from titles
2> go
                          
 ------------------------ 
                 5,300.00 

(1 row affected)
1> quit