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은 당신이 당신의 DB에서 UNIX 타임 스탬프가있는 경우 필요DATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
— Duncanmoo

감사합니다 @OMGPonies, 귀하의 구문으로 조건부 GROUP BY를 수행 할 수 있습니다.
— Henry

성능 ... 300,000 개 이상의 항목이있는 InnoDB 테이블에서 (~ GROUP BY YEAR(date), MONTH(date) DESC;450ms) 및 GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850ms )를 테스트 한 결과 전자 (이 질문에 대한 표시된 답변)가 후자보다 약 절반이 걸렸음을 보여주었습니다.
— ow3n

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

StackOverflow에 오신 것을 환영합니다! 이것은 오래되고 이미 답변 된 질문입니다. 더 긴급한 질문에도 기여해 주시면 기쁩니다. 여기에서 좋은 답변을 제공하기위한 팁을 찾을 수 있습니다 .
— Mifeet 2014

위의 답변에 대한 내 의견을 참조하십시오 ... 큰 테이블 에서이 방법은 두 배가 걸립니다.
— 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

나는 이것이 오래된 질문이라는 것을 알고 있지만 DB 수준에서 월 이름이 필요하지 않으면 다음이 작동합니다.

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

EXTRACT 함수 문서보기

성능이 더 좋을 것입니다. 응용 프로그램 계층에서 JSON 개체를 빌드하는 경우 결과를 실행하면서 서식 지정 / 순서를 지정할 수 있습니다.

NB MySQL의 GROUP BY 절에 DESC를 추가 할 수 있다는 것을 몰랐습니다. 아마도 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
— 에드가 오르테가

@EdgarOrtega 네,하지만 응용 프로그램 논리를 사용하여 원래 질문에서 원하는 JSON 개체를 생성하기에 충분해야합니다. 쿼리 결과에 대한 어떤 형태의 루핑이 이미 발생하고 있다고 가정 할 때, 제 접근 방식은 가능한 한 간단하고 빠르게 DB에서 필요한 최소한의 정보를 얻는 것을 목표로합니다
— Arth

1
당신 말이 맞아요. 내 의견은 그 함수의 출력이 어떤 것인지를 나타내는 것뿐입니다. 누군가가 그 형식을 좋아하지 않을 수도 있습니다.
— Edgar Ortega

@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 개월까지 주문하고 싶다고 가정 해 보겠습니다.


1

다음과 같이 EXTRACT 함수를 사용하십시오.

mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
       -> 2009

1

이것이 내가하는 방법입니다.

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);


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가 어떤 이유로 인해 월을 제대로 주문하지 않는 것처럼 보이지만 ...
— Derek Adair
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.