[thesite] database: content table

rudy r937 at interlog.com
Sat May 26 00:07:30 CDT 2001


> I love steadfast rules like the one
> you are implying in that first sentence.

thanks, joshua

not sure i can do the subject justice in one post (database books usually
devote an entire chapter to group by and having) but here goes...

suppose you have a database of city data

create table census
  (cityname  char(50)
  , county  char(2) references countytable
  , state  char(2) references statetable
  , men  integer
  , women integer
  , dogs integer
  , cats integer)

each city has foreign keys to its state and county, plus some demographic
data

there's one row per city

now let's look at a query

  select county, count(*)
      from census
   group by county

you get one row per group, i.e. one per county, and it contains the number
of cities -- actually rows, but there's one row per city in the table -- in
each county

try another

  select state, sum(dogs)
   from census
     group by state

again, one row per group, i.e. one row per state

now it gets trickier

  select  state, county, avg(men), avg(women)
    from census
      group by state, county

notice that the columns in the group by are also in the select list

you get one row per county per state, and the averages in this case are
city averages

the rows in the result set produced by a group by operation are similar to
the "subtotals" rows you get in report writer programs if you turn "details
off" (if you know what i mean)

it's kinda like you did a select distinct on the group by columns, to get
all the different combinations, but at the same time, producing subtotals
(counts, sums averages, etc.) for each distinct group

and don't forget the having clause, it can be quite useful too  --

  select cityname, count(state)
     from census
    group by cityname
     having count(state)>1

finds all citynames that exist in more than one state (tricky, but it's a
byproduct of the one-to-many relationship from state to city, nobody said
city names had to be unique)

what about this --

   select sum(dogs), sum(cats)
     from census

where's the group by??  don't really need one!!

the entire table is the group, so you only get one row back

see, any time you have a group by, the columns in the group by have to be
in the select list too

  select state, sum(cats)
    from census

bzzzzt,  this gives an error, you can't have an aggregate function without
the group by if there's a plain old ordinary column in the select list

you'd think that the database would be smart enough to just plug in the
group by columns whenever you use an aggregate function in the select list,
but noooooo....


finally, one caveat -- MySQL is a bit wacky when it comes to groups

7.4.13  Functions for Use with GROUP BY Clauses
http://www.mysql.com/documentation/mysql/bychapter/manual_Reference.html#Gr
oup_by_functions">

   MySQL has extended the use of GROUP BY. You can use
   columns or calculations in the SELECT expressions that don't
   appear in the GROUP BY part. This stands for any possible value
   for this group. You can use this to get better performance by
   avoiding sorting and grouping on unnecessary items. For example,
   you don't need to group on customer.name in the following query:

   mysql> select order.custid,customer.name,max(payments)
         from order,customer
         where order.custid = customer.custid
         GROUP BY order.custid;

   In ANSI SQL, you would have to add customer.name to the
   GROUP BY clause. In MySQL, the name is redundant if you
   don't run in ANSI mode.

   <STRONG>Don't use this feature</STRONG> if the columns
   you omit from the GROUP BY part aren't unique in the group!
   You will get unpredictable results.

i personally have not had a chance to play with this wackiness, and i'm not
eager to...



helps?

rudy







More information about the thesite mailing list