당연히 한번의 SQL로 가능합니다.
이때 통계를 내고자 하는 테이블말고, 다른 테이블의 도움이 필요합니다.
보통 업무상 달력테이블을 많이 만들어 씁니다.
일단 달력테이블을 만들고 통계를 내고자 하는 연도의 일자를 모두 입력해 둡니다.
'20030101'부터 '20031231'까지 입력합니다.
그리고 나서 시작 + 종료되어 있는 테이블과 BETWEEN 조인을 합니다.
보통 조인하면 "="만 생각하시는데 모든 관계연산자로 조인이 가능합니다.
달력테이블과 통계를 내고자 하는 테이블과 조인을 하게 되면 시작점과 종료점 사이에 존재하는
모든 점들이 복제되어 나타납니다.
"달력일자 BETWEEN 시작일 AND 종료일" 이렇게 조인합니다.
이제 복제된 데이터를 년월을 기준으로 카운트한 다음 다시 월별로 집계를 내주기만 하면 됩니다.
아래는 제가 작성한 SQL입니다.
SELECT U_NAME,
ISNULL(SUM(CASE WHEN YYMM = '200301' THEN CNT END),0) [1월],
ISNULL(SUM(CASE WHEN YYMM = '200302' THEN CNT END),0) [2월],
ISNULL(SUM(CASE WHEN YYMM = '200303' THEN CNT END),0) [3월],
ISNULL(SUM(CASE WHEN YYMM = '200304' THEN CNT END),0) [4월],
ISNULL(SUM(CASE WHEN YYMM = '200305' THEN CNT END),0) [5월],
ISNULL(SUM(CASE WHEN YYMM = '200306' THEN CNT END),0) [6월],
ISNULL(SUM(CASE WHEN YYMM = '200307' THEN CNT END),0) [7월],
ISNULL(SUM(CASE WHEN YYMM = '200308' THEN CNT END),0) [8월],
ISNULL(SUM(CASE WHEN YYMM = '200309' THEN CNT END),0) [9월],
ISNULL(SUM(CASE WHEN YYMM = '200310' THEN CNT END),0) [10월],
ISNULL(SUM(CASE WHEN YYMM = '200311' THEN CNT END),0) [11월],
ISNULL(SUM(CASE WHEN YYMM = '200312' THEN CNT END),0) [12월]
FROM (
SELECT U_NAME, SUBSTRING(CALDAT,1,6) YYMM, SUM(1) CNT
FROM TEST INNER JOIN CAL ON
CALDAT BETWEEN DATE_FR AND DATE_TO
GROUP BY U_NAME, SUBSTRING(CALDAT,1,6)) A
GROUP BY U_NAME
|