22

I want to select only the row which has max b.enddate for u.classno, u.userno. But it doesn't work.

select u.classno, u.userno, b.enddate
from libUser u
join book b on b.id = u.bookid
group by u.classno, u.userno
having b.enddate=max(b.enddate) //doesn't works
Satyam Koyani
  • 4,236
  • 2
  • 22
  • 48
karlkeller
  • 1,251
  • 3
  • 12
  • 22

2 Answers2

61

Here is an excellent article in the official MySQL documentation, but only standard SQL is used there, so it can be applied to whatever RDBMS you are using.

The Rows Holding the Group-wise Maximum of a Certain Column

Task: For each article, find the dealer or dealers with the most expensive price.

This problem can be solved with a subquery like this one:

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

The preceding example uses a correlated subquery, which can be inefficient (see Section 13.2.10.7, “Correlated Subqueries”). Other possibilities for solving the problem are to use an uncorrelated subquery in the FROM clause or a LEFT JOIN.

Uncorrelated subquery:

SELECT s1.article, dealer, s1.price
FROM shop s1
JOIN (
  SELECT article, MAX(price) AS price
  FROM shop
  GROUP BY article) AS s2
  ON s1.article = s2.article AND s1.price = s2.price;

LEFT JOIN:

SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
WHERE s2.article IS NULL;

The LEFT JOIN works on the basis that when s1.price is at its maximum value, there is no s2.price with a greater value and the s2 rows values will be NULL.

thebenman
  • 1,621
  • 14
  • 35
fancyPants
  • 50,732
  • 33
  • 89
  • 96
10

Whats wrong with:

select u.classno, u.userno, MAX(b.enddate)
from libUser u
join book b on b.id = u.bookid
group by u.classno, u.userno
Filip
  • 656
  • 4
  • 8
  • 8
    This answer is **perfectly correct**. But in case someone needs this: This approach isn't always reliable as it will pick **any** row value for non-groped columns viz. `u.classno` and `u.userno` **if they are not included in the group by clause** the value may not be from the same row as `MAX(b.enddate)` is picked from. Usually, it is the first row from each `group` that may change depending on the `order by` clause. I verified this on `MySQL` before writing here. MS-SQL does not allow such query at all. Don't know about other RDBMS. – Izhar Aazmi Apr 22 '15 at 09:57