WHERE filters results before they are grouped.
HAVING filters results after they are grouped.
correct:
count players by team:
SELECT COUNT(*) count, plheight_ft
FROM ALplayers
WHERE plheight_ft = 6
GROUP BY plheight_ft
ORDER BY count
error:
SELECT COUNT(*) count, plheight_ft
FROM ALplayers
WHERE count = 6 // <-------- error!
GROUP BY plheight_ft
ORDER BY count
correct:
SELECT COUNT(*) count, plheight_ft
FROM ALplayers
GROUP BY plheight_ft
HAVING count = 6
ORDER BY count
we want to see if/how-many people have the same name:
(remove duplicate records)
1st, just look at a few:
SELECT plplyrid, plNamef, plNamel, plpaddress
FROM ALplayers
WHERE plgameyear = '2006'
ORDER BY plNamel, plNamef
LIMIT 0, 44
…there may be about 4 duplicates and about 10+ brothers/cousins
SELECT COUNT(*) as count, plplyrid, plNamef, plNamel,
concat(substring(plNamef, 1, 1), plNamel) as ckname,
plpaddress
FROM ALplayers
WHERE plgameyear = '2006'
GROUP BY ckname
HAVING count > 1
ORDER BY ckname
( — o.k. — I saw 7 dups.(2 each) )
now, to see those people:
1st way: join table to itself.
SELECT DISTINCT p1.plplyrkey, p1.plplyrid, p1.plNamef, p1.plNamel,
concat(substring(p1.plNamef, 1, 1), p1.plNamel) as ckname,
p1.plpaddress, p1.plschlkey, p1.plheight_ft
FROM ALplayers as p1, ALplayers as p2
WHERE p1.plgameyear = '2006'
AND p2.plgameyear = '2006'
AND concat(substring(p1.plNamef, 1, 1), p1.plNamel) =
concat(substring(p2.plNamef, 1, 1), p2.plNamel)
AND p1.plplyrid != p2.plplyrid
ORDER BY ckname
— ahha, 3 of the 7 are brothers or cousins with the same 1st initial.
now, to see those people again:
2nd way: sub-query. (works in mysql 5.x)
SELECT p1.plplyrkey, p1.plplyrid, p1.plNamef, p1.plNamel,
concat(substring(p1.plNamef, 1, 1), p1.plNamel) as ckname,
p1.plpaddress, p1.plschlkey, p1.plheight_ft
FROM ALplayers as p1
WHERE p1.plgameyear = '2006'
HAVING ckname IN
(SELECT concat(substring(p2.plNamef, 1, 1), p2.plNamel) as p2ckname
FROM ALplayers as p2
WHERE p2.plgameyear = '2006'
GROUP BY p2ckname
HAVING count(*) > 1 )
ORDER BY ckname
# display duplicate records, if there are any (only works in mysql 5.x) :
SELECT h1.orderid
FROM oltohead as h1
HAVING orderid IN
(SELECT h2.orderid
FROM oltohead as h2
GROUP BY h2.orderid
HAVING count(*) > 1 )
ORDER BY h1.orderid
To find the customers with total orders of less than 100.
SELECT Customer, SUM(OrderPrice)
FROM Orders
GROUP BY Customer
HAVING SUM(OrderPrice) < 100
To find if the customers "Jones" or "Smith" have total orders of more than 300.
SELECT Customer, SUM(OrderPrice)
FROM Orders
WHERE Customer='Jones'
OR Customer='Smith'
GROUP BY Customer
HAVING SUM(OrderPrice) > 300
The HAVING clause can refer to aggregate functions, which the WHERE clause cannot:
SELECT user, MAX(salary)
FROM users
GROUP BY user
HAVING MAX(salary) > 10;
To find duplicates on a field that hasn't been uniquely indexed, you can do this:
SELECT BookISBN, count(BookISBN)
FROM Books
GROUP BY BookISBN HAVING COUNT(BookISBN) > 1;