Групповой максимум определенного столбца - PullRequest
4 голосов
/ 29 сентября 2011

У меня есть таблица:

SELECT * FROM shop;

+---------+--------+------
| article | dealer | price
+---------+--------+------
|    0001 | A      |  3.45
|    0001 | B      |  3.99
|    0002 | A      | 10.99
|    0003 | B      |  1.45
|    0003 | C      |  1.69
|    0003 | D      |  1.25
|    0004 | D      | 19.95
+---------+--------+------
7 rows in set (0.20 sec)

И я хочу получить - для каждой статьи - дилера или дилеров с самой дорогой ценой.

Может кто-нибудь сказать мне, почемуэто не работает?

SELECT article, dealer, MAX(price) FROM shop GROUP BY(article);

Для этого запроса я получаю следующий набор результатов;

+---------+--------+------------+
| article | dealer | MAX(price) |
+---------+--------+------------+
|    0001 | A      |       3.99 |
|    0002 | A      |      10.99 |
|    0003 | B      |       1.69 |
|    0004 | D      |      19.95 |
+---------+--------+------------+
4 rows in set (0.03 sec)

Несмотря на то, что максимальные цены верны, я нашел неправильных дилеров для некоторых товаров.

Ответы [ 5 ]

4 голосов
/ 29 сентября 2011

По вашему вопросу кажется, что вы уже читали статью о групповом максимуме определенного столбца , однако вы просто не понимаете, почему упомянутый вами метод не работает так, как вы ожидаете.

Давайте представим запрос, подобный следующему:

SELECT article, dealer, MAX(price), MIN(price) 
FROM shop 
GROUP BY article

Какое значение дилера вы ожидаете?

Я думаю, что это ответ на ваш вопрос.

2 голосов
/ 29 сентября 2011

Вот, пожалуйста:

SELECT article, dealer, price
FROM (SELECT article, dealer, price
      FROM shop
      ORDER BY price DESC) AS h
GROUP BY article

Это решение даже не требует функции MAX ().:)

Примечание: Это решение не работает с ONLY_FULL_GROUP_BY active и работает только в MySQL.Это решение в определенной степени не поддерживается из-за отсутствия документации, подтверждающей такое поведение.Он хорошо работает для меня и всегда работал хорошо для меня.

Этот метод все еще работает на последних MySQL на sqlfiddle .

1 голос
/ 29 сентября 2011

Стандартный SQL отклонил бы ваш запрос, потому что вы не можете SELECT неагрегированные поля, которые не являются частью предложения GROUP BY в агрегированном запросе.

Вы используете расширение MySQL SQL, описанное здесь :

MySQL расширяет использование GROUP BY, так что список выбора может ссылаться на неагрегированные столбцыне указано в предложении GROUP BY.Это означает, что предыдущий запрос является допустимым в MySQL.Вы можете использовать эту функцию для повышения производительности, избегая ненужной сортировки и группировки столбцов.Однако это полезно, прежде всего, когда все значения в каждом неагрегированном столбце, не названном в GROUP BY, одинаковы для каждой группы. Сервер может выбрать любое значение из каждой группы, поэтому, если они не совпадают, выбранные значения являются неопределенными .

0 голосов
/ 07 февраля 2015

Я просто размышлял над этим вопросом и удивляюсь, почему никто не приходит к идее объединить таблицу с самим собой, как описано в некоторых руководствах (см. Ссылки ниже).

Поэтому я бы предложил следующее решение:

Select A.* 
From      shop As A 
Left Join shop As B On  A.article
                     =  B.Article 
                    AND A.price 
                      < B.price 
Where B.price Is Null;

Магия очевидна: присоедините таблицу к себе и свяжите все записи в ней с любой другой записью, имеющей более высокую цену.Из них возьмите только те, у которых НЕТ связанных записей с более высокой ценой (поскольку эти записи - те, которые имеют самую высокую цену).

Насколько я знаю, это решение является даже лучшим с точки зрения производительности.

Эта часть документации MySQL и / или эта очень интересная статья Яна Кнешке может быть полезна - наслаждайтесь!

0 голосов
/ 29 сентября 2011

Это не работает, потому что если вы используете группирование по, вы не можете использовать отдельные поля исходных строк (кроме поля, по которому вы группируете). Правильный способ сделать это состоит в том, чтобы сделать внутренний / вложенный запрос для выбора дилера, вот так пососите (я не проверял, так что он может быть немного отключен):

SELECT article, MAX(price) as maxPrice, (SELECT dealer FROM shop AS s2 WHERE s2.article = s1.article AND s2.price = maxPrice) AS expensiveDealer FROM shop AS s1 GROUP BY(article);

...