2010-08-28 4 views
7

У меня есть таблица под названием order, которая содержит столбцы id, user_id, price и item_id. Цены на товары не фиксированы, и я хотел бы выбрать самый дорогой заказ каждого товара. Я хочу выбрать user_id, item_id и price в том же запросе. Я попробовал следующий запрос, но не вернул правильный набор результатов.Выберите несколько максимальных значений

SELECT user_id, item_id, MAX(price) 
FROM order 
GROUP BY item_id 

Некоторые из строк, возвращаемых этим запросом, имеют неправильный user_id. Тем не менее, все строки в результирующем наборе показывают правильную максимальную цену каждого товара.

ответ

9

Вы можете использовать производную таблицу следующим образом:

SELECT o1.item_id, o1.max_price, o2.user_id user_of_max_price 
FROM  (
      SELECT item_id, MAX(price) max_price 
      FROM `order` 
      GROUP BY item_id 
     ) o1 
JOIN  `order` o2 ON (o2.price = o1.max_price AND o2.item_id = o1.item_id) 
GROUP BY o1.item_id; 

Контрольный пример:

CREATE TABLE `order` (user_id int, item_id int, price decimal(5,2)); 

INSERT INTO `order` VALUES (1, 1, 10); 
INSERT INTO `order` VALUES (1, 2, 15); 
INSERT INTO `order` VALUES (1, 3, 8); 
INSERT INTO `order` VALUES (2, 1, 20); 
INSERT INTO `order` VALUES (2, 2, 6); 
INSERT INTO `order` VALUES (2, 3, 15); 
INSERT INTO `order` VALUES (3, 1, 18); 
INSERT INTO `order` VALUES (3, 2, 13); 
INSERT INTO `order` VALUES (3, 3, 10); 

Результат:

+---------+-----------+-------------------+ 
| item_id | max_price | user_of_max_price | 
+---------+-----------+-------------------+ 
|  1 |  20.00 |     2 | 
|  2 |  15.00 |     1 | 
|  3 |  15.00 |     2 | 
+---------+-----------+-------------------+ 
3 rows in set (0.00 sec) 
+0

Он отлично работал. Спасибо, Дэниел! – Ohas

1

Ваш запрос группирует строки по item_id. Если у вас есть несколько предметов с item_id 1, с различными user_id, то выберет только первый user_id, а не user_id с самой высокой ценой.

+0

Да, это так. Итак, как мне добиться того, что я пытаюсь сделать здесь? Я пытаюсь выяснить, кто купил предмет по самой высокой цене и что это за цена. – Ohas

0

Вам также нужно будет группировать по элементу item_id AND user_id (показывая максимальную цену за элемент для каждого пользователя), или если вам нужен только элемент в группе, вам нужно переосмыслить столбец user_id. , например. показать максимальную цену за товар и показать LAST пользователю, внесшему изменения по цене, или показать максимальную цену за товар и показать пользователю, который сделал максимальную цену за товар и т. д. Посмотрите на this post для некоторых шаблонов для этого.

+0

Не могу получить предмет, его максимальную цену и пользователя, который сделал эту цену в одном запросе? – Ohas

2

Вам нужно сначала получить максимальную цену за каждый идентификатор товара, а затем присоединиться к order, чтобы получить записи, где был заказан предмет за максимальную цену. Должно работать что-то вроде следующего запроса. Хотя, он вернет все записи с максимальными ценами товара.

SELECT user_id, item_id, price 
FROM order o 
JOIN (
     SELECT item_id, max(price) max_price 
     FROM order 
     GROUP BY item_id 
    ) o2 
    ON o.item_id = o2.item_id AND o.price = o2.max_price; 
2

Это является пер- групповой максимум вопрос. Для этой общей проблемы есть various approaches. В MySQL это, как правило, быстрее и проще в использовании нуль-автообъединение, чем что-нибудь с участием подзапросов:

SELECT o0.user_id, o0.item_id, o0.price 
FROM order AS o0 
LEFT JOIN order AS o1 ON o1.item_id=o0.item_id AND o1.price>o0.price 
WHERE o1.user_id IS NULL 

т.е.. «Выберите каждую строку, где нет другой строки для того же элемента с более высокой ценой».

(Если две строки имеют одинаковую максимальную цену, которую вы получите как возвращенное. Что именно делать в случае равенства является общей проблемой для погруппной-максимальных решений.)

+1

Не показывает ли эталон [ссылка, предоставленная вами] (http://kristiannielsen.livejournal.com/6745.html), что метод производной таблицы (некоррелированный подзапрос) намного быстрее, чем null-self-join? ... Я также думал, что null-self-join немного быстрее в MySQL, и на самом деле я очень удивлен этими критериями. У меня есть чувство, что я сам буду делать некоторые тесты :) ... +1 в любом случае –

+1

Да, результаты, конечно же, будут варьироваться в зависимости от размера используемых таблиц и индексов. В прошлом я обычно считал, что null-self-join является самым быстрым в моем конкретном наборе данных, используя MySQL (поддержка подзапроса которого, как известно, относительно молода, возможно, не так оптимизирована, как могла бы быть). Было бы интересно исследовать более позднюю версию MySQL. – bobince

1
SELECT user_id, item_id, MAX(price) 
FROM order 
GROUP BY item_id 

SQL, который вы использовали, противоречит GROUP. Когда вы используете GROUP, MYSQL всегда будет выбирать FIRST user_id, но ВЫСОКАЯ цена, это причина, по которой пользователь ошибается, но цена правильная.

Вы можете попробовать добавить ORDER BY price DESC, чтобы узнать, что произойдет, но я не пробовал в своей среде.

3

Может быть, это немного больше времени, но вы получите в читаемость

SELECT 
     * 
FROM 
    `order` 
JOIN 
    (
     SELECT 
      item_id, 
      MAX(price) price 
     FROM 
      `order` 
     GROUP BY 
      item_id 
    ) 
    USING(item_id, price); 
0

если вы хотите топ 2 от того, попробуйте это ...

если вы хотите топ 3, то просто изменить последнее условие где item_rank in (1,2) ; до where item_rank in (1,2,3) ;

select * from 
    (select item_id , price 
    , @curRow % @curNval as item_rank 
    , @curRow := @curRow + 1 AS row_number 
    from `order` , (SELECT @curRow := 1 , @curNval := 3) r 
    order by item_id , price desc ) tab where item_rank in (1,2) ; 
+0

может использоваться как item_rank> 2 или item_rank> n – Kapil

Смежные вопросы