Как написать запрос типа «наибольшее число на группу», но с дополнительными условиями? - PullRequest
5 голосов
/ 23 марта 2012

Я задал вопрос о создании запроса типа «наибольшее число на группу» вчера (в то время, когда он не знал, что он называется «наибольшее число на группу»), за исключением того, что я спросил, как получить наименьшее количество на группу. Структура таблицы была следующей:

type    name    value
=====================
1       item1    1
1       item2    20
2       item3    0
3       item4    5
3       item5    2
3       item6    50

Я получил несколько хороших ответов, и самый полезный был таким:

SELECT t1.type, t1.name, t1.value
FROM mytable t1
LEFT JOIN mytable t2 ON t1.type = t2.type AND t1.value > t2.value
WHERE t2.value IS NULL

Приведенный выше запрос приводит к следующему:

type    name    value
=====================
2       item3    0
1       item1    1
3       item5    2

Тем не менее, после того, как я задал вопрос, я понял, что пропустил важное требование, которое, похоже, не могу понять, как добавить к вышеуказанному запросу. Мне нужно добавить условный оператор, который вместо выбора строки с наименьшим значением для столбца в группе выбирает строку с наименьшим значением для столбца в группе, но где в этой строке есть другой столбец со значением больше чем какое-то минимальное значение.

Вот мой новый вопрос / проблема:


У меня есть следующая таблица (продукты):

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    0   |    0     |   item1  |      3.5       |   0.99    |
|    3   |    1     |   item2  |      3         |   1.99    |
|    4   |    1     |   item3  |      6         |   2.95    |
|    6   |    1     |   item4  |      9         |   2.50    |
|    9   |    1     |   item5  |      12        |   3.75    |
|    12  |    2     |   item6  |      16        |   5.25    |
|    13  |    2     |   item7  |      32        |   10.95   |
|    14  |    2     |   item8  |      48        |   7.50    |
+-----------------------------------------------------------+

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

Итак, скажем, что популярность должна быть больше 3, тогда результат должен быть:

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    0   |    0     |   item1  |      3.5       |   0.99    |
|    6   |    1     |   item4  |      9         |   2.50    |
|    12  |    2     |   item6  |      16        |   5.25    |
+-----------------------------------------------------------+

Если популярность должна быть больше 6, то результат должен быть:

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    6   |    1     |   item4  |      9         |   2.50    |
|    12  |    2     |   item6  |      16        |   5.25    |
+-----------------------------------------------------------+

Надеюсь, я правильно сделал оба этих примера. В любом случае, я думаю, вы поняли.

Можно ли сделать то, что я спрашиваю, одним запросом?

1 Ответ

4 голосов
/ 23 марта 2012

Это требует некоторого внимания, где поставить условие (where или on?), Чтобы вас не обманули :-) Вам нужно добавить условие для предложения t1 в where и для предложение от t2 до on:

SELECT t1.type, t1.name, t1.value
FROM mytable t1
LEFT JOIN mytable t2 ON t1.type = t2.type AND t1.value > t2.value 
    AND t2.popularity > 3 /* here */
WHERE t2.value IS NULL 
    AND t1.popularity > 3 /* and here */

Не проверял, но он должен работать.

Попытка объяснения: условие, в котором предложение where влияет на то, какие элементы вы считаете потенциальными элементами с наименьшим значением. Принимая во внимание, что условие в предложении on влияет на связь: с какими другими элементами вы хотите сравнить его? Он определяет группу, в которой вы сравниваете. Технически, это влияет на то, когда t2. * Будет NULL. Если бы вместо этого вы указали условие для t2.popularity в предложении where, вы бы не получили NULL (т.е. не находите элементы с наименьшим значением) для групп, где самые низкие элементы имеют низкую популярность.

...