MySQL에서 주별로 그룹화하는 방법은 무엇입니까?


93

Oracle의 테이블 서버는 내장 기능인 TRUNC(timestamp,'DY'). 이 함수는 모든 타임 스탬프를 이전 일요일의 자정으로 변환합니다. MySQL에서이를 수행하는 가장 좋은 방법은 무엇입니까?

오라클은 TRUNC(timestamp,'MM')타임 스탬프가 발생하는 달의 1 일 자정으로 변환 할 수도 있습니다 . MySQL에서 이것은 간단합니다.

TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))

그러나이 DATE_FORMAT트릭은 몇 주 동안 작동하지 않습니다. 나는 그 WEEK(timestamp)기능을 알고있다 . 그러나 나는 정말로 1 년 안에 주 번호를 원하지 않는다. 이 물건은 다년간의 작업입니다.


trunc (sysdate, 'DY')가 아니라 trunc (sysdate, 'W')를 의미합니다.
David Aldridge

TRUNC(date, 'DY' )일요일 시작으로 몇 주를 얻습니다. 'W'적어도 내 시스템에서 월요일 시작됩니다.
O. Jones

답변:


123

YEAR(timestamp)및을 모두 사용할 수 있으며 및 절 WEEK(timestamp)에서 이러한 식을 모두 사용할 수 있습니다 .SELECTGROUP BY

지나치게 우아하지는 않지만 기능적 ...

물론이 두 날짜 부분을 단일 표현식으로 결합 할 수도 있습니다.

SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc...
FROM ...
WHERE ..
GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))

편집 : Martin이 지적했듯이YEARWEEK(mysqldatefield) , 그 출력은 위의 긴 공식만큼 눈에 친숙하지 않지만 함수 를 사용할 수도 있습니다 .


편집 2 [3 1/2 년 후!] :
YEARWEEK(mysqldatefield)선택 사항 인 두 번째 인수 ( mode)를 0 또는 2로 설정하는 것이 아마도 완전한 주 단위 로 집계하는 가장 좋은 방법 일 것입니다 (즉, 1 월 1 일에 걸쳐있는 주 포함). 원하는 것. YEAR() / WEEK()처음이 답변에서 제안 된 접근 방식은 분할의 효과 등의 집계 데이터가 "벌리고" 이전 해 하나, 새해과 하나 : 두 주.
회계 등에서 최대 2 주 (양쪽 끝에 하나씩)를 두는 비용으로 매년 깔끔하게 절단하는 것이 바람직하며이 YEAR() / WEEK()방법이 더 좋습니다.


12
YEARWEEK()결과는 INT(6)정렬 / 결합 / 그룹화가 더 빠르다고 생각합니다
KCD

1
@mjv : 2 년이 같은 주를 공유하면 어떻게 되나요? 2012 년 12 월 31 일부터 2013 년 6 월 1 일까지 (월 ~ 일) 이것에 대한 해결책이 있습니까?
hardik

@hardik : 편집 2 참조. 필요에 따라 YEARWEEK ()는 한 해의 마지막 / 첫 부분 주를 분할하는 것보다 완전한 주로 작업하는 것이 더 낫다면 집계하기에 더 좋은 키가 될 수 있습니다.
mjv

@mjv 여기에 또 다른 솔루션입니다 링크
hardik

"타임 스탬프"가 내 테이블에있는 것처럼 정수가 아닌지 확인하십시오. WEEK (timestamp)는 날짜 / 타임 스탬프 열 유형을 유효한 인수로 사용합니다.
Usman Shaukat

40

위의 대답은 시간순이 아닌 알파벳순으로 주를 정렬했기 때문에 저에게 효과적이지 않았습니다.

2012/1
2012/10
2012/11
...
2012/19
2012/2

다음은 주 단위로 계산하고 그룹화하는 솔루션입니다.

SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, 
       YEAR(date), WEEK(date), COUNT(*)
FROM column_name
GROUP BY week_name
ORDER BY YEAR(DATE) ASC, WEEK(date) ASC

생성 :

YEAR/WEEK   YEAR   WEEK   COUNT
2011/51     2011    51      15
2011/52     2011    52      14
2012/1      2012    1       20
2012/2      2012    2       14
2012/3      2012    3       19
2012/4      2012    4       19

5
날짜 ( ORDER BY date ASC)로 주문하는 것도 트릭을해야합니다
Fender

36

알아 냈어 ... 조금 번거롭지 만 여기 있습니다.

FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))

비즈니스 규칙에 따라 주가 월요일에 시작된다고되어 있으면 -1-2.


편집하다

몇 년이 지났고 마침내 나는 이것을 작성했습니다. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/


@Ollie-가독성을 높이기 위해 DAYOFWEEK () 또는 WEEKDAY () 사용을 고려합니다.
martin clayton

1
Martin, 나는 그것을 고려했고 그 함수들이 월요일-일요일 0-6으로 실행된다는 것을 발견했습니다. 내 비즈니스 규칙에 따르면 주가 일요일 00:00에 시작되므로 WEEKDAY 항목이 약간 추악 해졌습니다. 가독성에 대한 귀하의 말이 맞습니다.
O. Jones

@OllieJones 완벽 해! 정말 고맙습니다!
Joe Cheng

1
훌륭한 솔루션과 기사. 감사합니다!
Jeremy Wiggins

첫 번째 날로 "월요일"을 설정하는 방법이 있습니까?
Pedro Joaquín

25

YEARWEEK () 함수를 사용하여 연결된 연도와 주 번호 (200945)를 얻을 수 있습니다 . 목표를 올바르게 이해하면 다년 데이터를 그룹화 할 수 있습니다.

한주의 시작에 대한 실제 타임 스탬프가 필요한 경우 그다지 좋지 않습니다.

DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )

월별 주문의 경우 LAST_DAY () 함수를 고려할 수 있습니다. 정렬은 해당 월의 마지막 날을 기준으로하지만 이는 해당 월의 1 일 기준으로 정렬하는 것과 동일해야합니다.


1
+1 마틴. 저 한테는 YEARWEEK ()에 대해 잊었습니다 ... 그냥 많이 사용하지 않습니다.
mjv

4

선택에서 이것을 광고하십시오 :

DATE_FORMAT($yourDate, \'%X %V\') as week

group_by(week);

방법 그룹에 월별
라비 테자

연속적으로 데이터를 수집하지 않고 특정 날짜에 대해서만
Chique_Code

2

"주 종료"날짜가 필요한 경우에도 작동합니다. 이것은 매주 기록의 수를 계산합니다. 예 : 2010 년 1 월 9 일과 2010 년 1 월 16 일 사이에 (포함) 2010 년 1 월 9 일과 2010 년 1 월 16 일 사이에 3 개의 작업 주문이 생성되고 5 개가 (포함) 2010 년 1 월 9 일과 1/16/2010 사이에 생성 된 경우 다음이 반환됩니다.

3 1/8/2010
5 1/16/2010

내 datetime 필드를 자르려면 추가 DATE () 함수를 사용해야했습니다.

SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending
FROM work_order wo
GROUP BY week_ending;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.