mysql ORDER BY MIN () не соответствует идентификатору

У меня есть база данных со следующими столбцами:

-------------------
id|domain|hit_count
-------------------

И я хотел бы выполнить на нем такой запрос:

SELECT id,MIN(hit_count)
  FROM table WHERE domain='$domain'
 GROUP BY domain ORDER BY MIN(hit_count)

Я хотел бы, чтобы этот запрос дал мне идентификатор строки с наименьшим значением hit_count для $ domain. Единственная проблема заключается в том, что если у меня есть две строки с одним и тем же доменом, скажем, www.bestbuy.com, запрос будет просто сгруппирован по тому, какой из них пришел первым, а затем, хотя я получу правильное наименьшее значение hit_count, идентификатор может или может не быть идентификатором строки с наименьшим hit_count.

Кто-нибудь знает, как я могу выполнить этот запрос и получить идентификатор, соответствующий MIN (hit_count)? Спасибо!


person srchulo    schedule 22.06.2012    source источник
comment
не используйте table в качестве имени таблицы. table - это зарезервированное ключевое слово в MYSQL   -  person Fahim Parkar    schedule 22.06.2012
comment
Спасибо. Я просто использовал это для примера вместо своего настоящего имени таблицы. Хотя это полезно знать.   -  person srchulo    schedule 03.07.2012


Ответы (6)


Попробуй это:

SELECT id,MIN(hit_count),domain FROM table GROUP BY domain HAVING domain='$domain'
person Bishnu Paudel    schedule 22.06.2012
comment
Это требует объяснения. Если я что-то не упускаю, он также забывает ЗАКАЗ, который хотел задать спрашивающий. - person kevmitch; 26.01.2018

Видите ли, когда вы используете агрегаты, либо через агрегатные функции (а min() является такой функцией), либо с помощью операторов GROUP BY или HAVING, ваши данные группируются. В вашем случае они сгруппированы по доменам. В вашем списке выбора есть 2 поля: id и min(hit_count).

Теперь для каждой группы база данных знает, какой hit_count выбрать, поскольку вы явно указали это через агрегатную функцию. А как насчет id - какой из них включить? MySQL внутренне оборачивает такие поля в max() агрегатную функцию, что, как я считаю, подвержено ошибкам. Во всех других СУБД вы получите ошибку для такого запроса.

Правило: если вы используете агрегаты, то все столбцы должны быть либо аргументами агрегатных функций, либо аргументами оператора GROUP BY.

Для достижения желаемого результата понадобится подзапрос:

SELECT id, domain, hit_count
  FROM `table`
 WHERE domain = '$domain'
   AND hit_count = (SELECT min(hit_count) FROM `table` WHERE domain = '$domain');

Я использовал обратные кавычки, поскольку table - зарезервированное слово в SQL.

person vyegorov    schedule 22.06.2012

Попробуй это:

SELECT id,hit_count
  FROM table WHERE domain='$domain'
 GROUP BY domain ORDER BY hit_count ASC;

Это также должно работать:

select id, MIN(hit_count) from table where domain="$domain";
person vijay    schedule 22.06.2012
comment
вам просто нужен идентификатор строки с минимальным количеством совпадений для конкретного домена. правильно !! - person vijay; 22.06.2012
comment
как можно использовать агрегатную функцию без предложения GROUP BY при выборе нескольких полей? - person Bishnu Paudel; 22.06.2012
comment
почему мы не можем использовать агрегатную функцию без GROUP BY ?? И srchulo хочет только идентификатор строки с минимальным количеством конкретного домена. - person vijay; 22.06.2012
comment
вы не выбираете только идентификатор. вы выбираете id и min (hit_count) - person Bishnu Paudel; 22.06.2012
comment
да, я выбираю как id, так и min (hit_count). Это не проблема. Если я получаю строку, я могу также выбрать * (all) из этой строки. - person vijay; 22.06.2012

У меня был такой же вопрос. См. Этот вопрос ниже.

min (столбец) не возвращает мне правильные данные других столбцов

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

F1   |   F2
1         aa
1         bb
1         cc
2         gg
2         hh

Если вы сгруппируете по F1: SELECT F1,F2 from T GROUP BY F1 Вы получите две строки:

1    and one value from (aa,bb,cc)
2    and one value from (gg,hh)

Если вам нужен детерминированный набор результатов, вам нужно указать программе, какой алгоритм применить к группе. Несколько например:

  1. MIN
  2. МАКСИМУМ
  3. СЧИТАТЬ
  4. СУММ

и т. д. и т. д.

person Fahim Parkar    schedule 22.06.2012

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

SELECT
  id,
  MIN(hit_count)
FROM table
WHERE domain = '$domain'
GROUP BY domain DESC
ORDER BY MIN(hit_count) 

Объяснение:
Когда вы используете group by с агрегатной функцией, она всегда выбирает первую запись, но если вы ограничиваете ее ключевым словом desc, она выбирает самую низкую или последнюю запись этой группы. Для тестирования используйте этот запрос, в который добавлен только group_concat.

SELECT
  group_concat(id),
  MIN(hit_count)
FROM table
WHERE domain = '$domain'
GROUP BY domain DESC
ORDER BY MIN(hit_count) 
person Muhammad Raheel    schedule 22.06.2012

Если у вас может быть группа дублированных доменов по идентификатору:

SELECT id,MIN(hit_count)
FROM domain WHERE domain='$domain'
GROUP BY id ORDER BY MIN(hit_count)
person ssedano    schedule 22.06.2012