Группировка по месяцам и годам в MySQL


99

Учитывая таблицу с меткой времени в каждой строке, как бы вы отформатировали запрос, чтобы он соответствовал этому конкретному формату объекта json.

Я пытаюсь организовать объект json в годы / месяцы.

json для обоснования запроса:

{
  "2009":["August","July","September"],
  "2010":["January", "February", "October"]
}

Вот вопрос, который у меня есть -

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY MONTH(t.summaryDateTime) DESC";

Запрос не работает, потому что (как и ожидалось) объединяет разные годы.

Ответы:


188
GROUP BY YEAR(t.summaryDateTime), MONTH(t.summaryDateTime) DESC;

это то, что вы хотите.


63
+1: Еще одна альтернатива с использованием DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies

3
Далее, FROM_UNIXTIME необходим, если у вас есть временная метка UNIX в вашей БДDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Дунканму

Спасибо @OMGPonies, с вашим синтаксисом я могу выполнить условную GROUP BY.
Генри

Производительность ... мой тест GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 мс) и GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 мс) в таблице InnoDB с> 300 000 записей показал, что первое (отмеченный ответ на этот вопрос) заняло примерно половину времени, чем второе.
ow3n

78
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')

Добро пожаловать в StackOverflow! Это старый вопрос, на который уже дан ответ. Мы будем рады, если и вы сможете ответить на более актуальные вопросы. Вы можете найти советы о том, чтобы обеспечить хорошие ответы здесь .
Mifeet

См. Мой комментарий к ответу выше ... На больших таблицах этот метод занимает вдвое больше времени.
ow3n

9

я предпочитаю

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY EXTRACT(YEAR_MONTH FROM t.summaryDateTime) DESC";

8
SELECT MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM trading_summary t
GROUP BY YEAR(t.summaryDateTime) DESC, MONTH(t.summaryDateTime) DESC

Следует использовать DESC как для ГОДА, так и для Месяца, чтобы получить правильный порядок.


7

Я знаю, что это старый вопрос, но следующее должно работать, если вам не нужно название месяца на уровне БД:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month;

См. Документацию по функции EXTRACT

Вы, вероятно, обнаружите, что это работает лучше ... и если вы создаете объект JSON на уровне приложения, вы можете выполнять форматирование / упорядочивание по мере просмотра результатов.

NB Я не знал, что вы можете добавить DESC в предложение GROUP BY в MySQL, возможно, вам не хватает предложения ORDER BY:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month
ORDER BY summary_year_month DESC;

1
Пожалуйста , обратите внимание , что выход из EXTRACT(YEAR_MONTH FROM summaryDateTime)это201901
Эдгар Ortega

@EdgarOrtega Да, но этого должно быть достаточно для создания желаемого объекта JSON в исходном вопросе с использованием логики приложения. Предполагая, что какая-то форма зацикливания результата запроса уже происходит, мой подход направлен на получение минимально необходимой информации из БД как можно проще и быстрее
Арт

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

@EdgarOrtega Не беспокойтесь, спасибо, достойный вклад!
Arth

2

Вы должны сделать что-то вроде этого

SELECT onDay, id, 
sum(pxLow)/count(*),sum(pxLow),count(`*`),
CONCAT(YEAR(onDay),"-",MONTH(onDay)) as sdate 
FROM ... where stockParent_id =16120 group by sdate order by onDay

2

Вы звоните и делаете это

SELECT  SUM(amnt) `value`,DATE_FORMAT(dtrg,'%m-%y') AS label FROM rentpay GROUP BY YEAR(dtrg) DESC, MONTH(dtrg) DESC LIMIT 12

заказать по году и месяцу. Допустим, вы хотите сделать заказ в этом году и в этом месяце вплоть до 12 месяцев.





0
SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
FROM trading_summary t GROUP BY yr

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

Например, используйте PHP explode для создания массива из списка названий месяцев, а затем используйте json_encode ()


-2

Использовать

GROUP BY year, month DESC";

Вместо того

GROUP BY MONTH(t.summaryDateTime) DESC";

хотя похоже, что GROUP BY MONTH (t.summaryDateTime) DESC по какой-то причине не упорядочивает месяцы должным образом ...
Дерек Адэр
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.