Подтвердить что ты не робот

Как группировать по неделям в MySQL?

Сервер Oracle table предлагает встроенную функцию TRUNC(timestamp,'DY'). Эта функция преобразует любую временную метку в полночь в предыдущее воскресенье. Какой лучший способ сделать это в MySQL?

Oracle также предлагает TRUNC(timestamp,'MM') преобразовать временную метку в полночь в первый день месяца, в котором она происходит. В MySQL это просто:

TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))

Но этот трюк DATE_FORMAT не будет работать неделями. Я знаю о функции WEEK(timestamp), но мне действительно не нужен номер недели в течение года; этот материал предназначен для многолетней работы.

4b9b3361

Ответ 1

Разобрался... немного громоздко, но вот оно.

FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))

И, если ваши бизнес-правила говорят, что ваши недели начинаются по понедельникам, измените -1 на -2.


редактировать

Прошли годы, и я наконец-то нашел время написать это. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

Ответ 2

Вы можете использовать как YEAR(timestamp) и WEEK(timestamp), и использовать оба этих выражения в предложении SELECT и GROUP BY.

Не слишком элегантно, но функционально...

И, конечно, вы можете объединить эти две части даты в одном выражении, то есть что-то вроде

SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc...
FROM ...
WHERE ..
GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))

Редактировать: Как указывает Мартин , вы также можете использовать YEARWEEK(mysqldatefield), хотя ее вывод не так YEARWEEK(mysqldatefield) глаз, как более длинная формула выше.


Отредактируйте 2 [3,5 года спустя!]:
YEARWEEK(mysqldatefield) с необязательным вторым аргументом ( mode), установленным в 0 или 2, вероятно, является наилучшим способом агрегирования по целым неделям (т.е. включая недели, которые колеблются после 1 января), если это то, что нужно. Подход YEAR()/WEEK() первоначально предложенный в этом ответе, позволяет разделить агрегированные данные для таких "колеблющихся" недель на две части: одну с предыдущим годом, одну с новым годом.
Ежегодно необходимо проводить чистую срезку за счет наличия до двух неполных недель, по одной на каждом конце, часто в бухгалтерском учете и т.д., И в этом случае подход YEAR()/WEEK() лучше.

Ответ 3

Принятый ответ выше не работал у меня, потому что он заказывал недели по алфавиту, а не по хронологическому порядку:

2012/1
2012/10
2012/11
...
2012/19
2012/2

Здесь мое решение для подсчета и группировки по неделям:

SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, 
       YEAR(date), WEEK(date), COUNT(*)
FROM column_name
GROUP BY week_name
ORDER BY YEAR(DATE) ASC, WEEK(date) ASC

Формирует:

YEAR/WEEK   YEAR   WEEK   COUNT
2011/51     2011    51      15
2011/52     2011    52      14
2012/1      2012    1       20
2012/2      2012    2       14
2012/3      2012    3       19
2012/4      2012    4       19

Ответ 4

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

Если вам нужна фактическая отметка времени для начала недели, она менее приятная:

DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )

Для ежемесячного заказа вы можете рассмотреть функцию LAST_DAY() - сортировка будет в последний день месяца, но это должно быть эквивалентно к сортировке в первый день месяца... не так ли?

Ответ 5

Просто выберите это в списке:

DATE_FORMAT($yourDate, \'%X %V\') as week

И

group_by(week);

Ответ 6

Если вам нужна дата окончания недели, это также сработает. Это будет подсчитывать количество записей за каждую неделю. Пример. Если между (включительно) были созданы три рабочих заказа (включительно) 1/2/2010 и 1/8/2010 и 5 между (включительно) 1/9/2010 и 1/16/2010, это вернет:

3 1/8/2010
5 1/16/2010

Мне пришлось использовать дополнительную функцию DATE(), чтобы усечь мое поле datetime.

SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending FROM work_order wo GROUP BY week_ending;