Как получить все поля строки с помощью функции SQL MAX? - PullRequest
6 голосов
/ 24 мая 2010

Рассмотрим эту таблицу (от http://www.tizag.com/mysqlTutorial/mysqlmax.php):

Id     name               type     price 
123451 Park's Great Hits  Music    19.99 
123452 Silly Puddy        Toy      3.99 
123453 Playstation        Toy      89.95 
123454 Men's T-Shirt      Clothing 32.50 
123455 Blouse             Clothing 34.97 
123456 Electronica 2002   Music    3.99 
123457 Country Tunes      Music    21.55 
123458 Watermelon         Food     8.73

Этот запрос SQL возвращает самый дорогой элемент каждого типа: Тип SELECT, МАКС (цена) ИЗ ПРОДУКТОВ ГРУППА BY тип

Clothing $34.97
Food     $8.73
Music    $21.55
Toy      $89.95

Я также хочу получить поля id и name , которые относятся к максимальной цене, для каждой строки. Какой запрос SQL вернет таблицу, подобную этой?

Id     name            type      price
123455 Blouse          Clothing  34.97
123458 Watermelon      Food      8.73
123457 Country Tunes   Music     21.55
123453 Playstation     Toy       89.95

Ответы [ 3 ]

6 голосов
/ 24 мая 2010

Это проблема greatest-n-per-group, которая часто возникает. Мой обычный способ ее решения логически эквивалентен ответу, заданному @Martin Smith, но не использует подзапрос:

SELECT T1.Id, T1.name, T1.type, T1.price 
FROM Table T1
LEFT OUTER JOIN Table T2
  ON (T1.type = T2.type AND T1.price < T2.price)
WHERE T2.price IS NULL;

Мое решение и все остальные, приведенные в этой теме, могут создать несколько строк на значение type, если более одного продукта имеют одинаковый тип, и обе имеют одинаковую цену, которая является максимальной. Есть способы решить эту проблему и разорвать связь, но вы должны сообщить нам, какой продукт «выигрывает» в таком случае.

Вам нужен какой-то другой атрибут, который гарантированно будет уникальным для всех строк, по крайней мере, для строк с одинаковым type. Например, если продукт с большим значением Id должен выиграть, вы можете разрешить связь следующим образом:

SELECT T1.Id, T1.name, T1.type, T1.price 
FROM Table T1
LEFT OUTER JOIN Table T2
  ON (T1.type = T2.type AND (T1.price < T2.price
       OR T1.price = T2.price AND T1.Id < T2.Id))
WHERE T2.price IS NULL;
6 голосов
/ 24 мая 2010

Редактировать Просто обновить мой, чтобы удовлетворить уточненное требование

SELECT Id, name, type,price 
FROM Table T1
WHERE NOT EXISTS(
          SELECT * FROM TABLE T2 
          WHERE T1.type=t2.type 
          AND T2.Price >= T1.Price 
          AND T2.Id > T1.Id
          )
3 голосов
/ 24 мая 2010

Вы можете сделать это с помощью выбора

SELECT id, name, type, price FROM products p1
WHERE EXISTS (Select type, max(price) FROM Products p2 
              GROUP BY type
              WHERE p1.type=p2.type AND p1.price=p2.MAX(price))

или внутреннего соединения

SELECT id, name, type, price FROM products p1
INNER JOIN (Select type, max(price) FROM Products p2 GROUP BY type) maxPrice
         ON maxPrice=price=p1.price AND maxPrice.type=p1.price
...