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.