Групувати за місяцями та роками в MySQL


95

Отримавши таблицю з позначкою часу в кожному рядку, як би ви відформатували запит, щоб він містився у цьому конкретному форматі об’єкта 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";

Запит руйнується, оскільки він (передбачувано) поєднує різні роки.

Відповіді:


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

це те, що ви хочете.


60
+1: Інша альтернатива використання DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies

3
Далі, FROM_UNIXTIME потрібен, якщо у вашій БД є мітка часу UNIXDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo

Дякую @OMGPonies, за вашим синтаксисом я можу виконати умовний GROUP BY.
Генрі

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

77
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 на рівні програми, ви можете виконати форматування / упорядкування під час проходження результатів.

Примітка: Я не знав, що ви можете додати 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 Не хвилюйтесь, дякую, гідний внесок!
Арт

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's explode для створення масиву зі списку назв місяців, а потім використовуйте json_encode ()


-2

Використовуйте

GROUP BY year, month DESC";

Замість

GROUP BY MONTH(t.summaryDateTime) DESC";

хоча, схоже, GROUP ЗА МІСЯЦЬ (t.summaryDateTime) DESC чомусь не впорядковує місяці належним чином ...
Дерек Едір
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.