Группировка по месяцам и годам в 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 месяцев.

Niclausel
источник
1

Вы группируете только по месяцам, вам нужно добавить YEAR () в группу по

Эдуардо Раскон
источник
1

используйте функцию EXTRACT, как это

mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
       -> 2009
Ребаймелек
источник
1

Вот как я это делаю:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
CTBrewski
источник
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 ()

Mchl
источник
-2

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

GROUP BY year, month DESC";

Вместо того

GROUP BY MONTH(t.summaryDateTime) DESC";
Кира
источник
хотя похоже, что GROUP BY MONTH (t.summaryDateTime) DESC по какой-то причине не упорядочивает месяцы должным образом ...
Дерек Адэр