#mysql #datetime #group-by
#mysql #datetime #группировка по
Вопрос:
Если у меня есть такой запрос MySQL, суммируя частоту слов в неделю:
SELECT
SUM(`city`),
SUM(`officers`),
SUM(`uk`),
SUM(`wednesday`),
DATE_FORMAT(`dateTime`, '%d/%m/%Y')
FROM myTable
WHERE dateTime BETWEEN '2011-09-28 18:00:00' AND '2011-10-29 18:59:00'
GROUP BY WEEK(dateTime)
Результаты, выдаваемые MySQL, принимают первое значение столбца DateTime, в данном случае 28/09/2011, которое приходится на субботу.
Можно ли настроить запрос в MySQL, чтобы показать дату начала недели, даже если нет доступных данных, чтобы для приведенного выше 2011-09-28 было заменено на 2011/09/26 вместо этого? То есть дата начала недели, являющаяся понедельником. Или было бы лучше программно настроить даты после выполнения запроса?
Столбец DateTime имеет формат 2011/10/02 12:05:00
Ответ №1:
Это можно сделать в SQL, но было бы лучше сделать это в вашем программном коде, так как это было бы более эффективно и проще. Кроме того, хотя MySQL принимает ваш запрос, это не совсем имеет смысл — у вас есть DATE_FORMAT(dateTime, '%d/%m/%Y')
в списке полей выбора, пока вы группируете WEEK(dateTime)
. Это означает, что механизм БД должен выбирать случайную дату из текущей группы (недели) для каждой строки. Т.Е. считайте, что у вас есть записи для 27.09.2011
, 28.09.2011
и 29.09.2011
— все они попадают на одну неделю, поэтому в конечном наборе результатов для этих трех записей генерируется только одна строка. Теперь, какая дата из этих трех должна быть выбрана для вызова DATE_FORMAT()? Ответ был бы несколько проще, если бы ORDER BY
в запросе было указано, но по-прежнему не имеет смысла использовать поля / выражения в списке полей, которых нет GROUP BY
или которые не являются агрегатами. Вы действительно должны вернуть номер недели в списке выбора (вместо вызова DATE_FORMAT), а затем в своем коде вычислить даты начала и окончания из него.
Комментарии:
1. Не уверен, что я вполне понимаю ваш ответ. MySQL выдает мне дату и время первой строки для каждой группы недель, и для каждого DateTime в результатах я затем использую DATE_FORMAT для форматирования этого DateTime.
2. @MrMorgan, ain означает, что ваш запрос содержит логическую ошибку. Это неопределенно. Группа по объединит несколько строк, но будет показана только одна из этих строк. Выбранные вами неагрегированные поля всегда должны функционально зависеть от предложения group by . Самый простой способ сделать это — повторить все неагрегированные выборки в предложении group by .
3. @MrMorgan Смотрите мой обновленный ответ, надеюсь, теперь он объясняет это лучше. Так получилось, что MySQL выбирает нужную вам дату, но это детали реализации, которые вам действительно не следует передавать!
4. @Johan: Жаль, что это удаляет значение DateTime из списка полей, хотя его можно заменить программно, как предлагает AIN.
5. Йохан имеет в виду, что если вы хотите использовать
DATE_FORMAT(dateTime, '%d/%m/%Y')
список полей in, вы также должны добавить его вGROUP BY
(или в этом случае добавитьdateTime
в group by). Но это даст вам другой результирующий набор, отличный от того, который вы хотите, поэтому вам нужно использовать какой-то другой подход…