GroupBy 와 Having
MySQL에서 유형별로 갯수를 가져오고 싶은데, 단순히 COUNT 함수로 데이터를 조회하면 전체 갯수만을 가져온다.
이렇게 유형별로 갯수를 알고 싶을 때는 컬럼에 데이터를 그룹화 할 수 있는 GROUP BY를 사용하는 것이다.
GROUP BY를 사용할 때는 두가지를 기억하자.
- Group By : 특정 컬럼을 그룹화 한다.
- Having : 특정 컬럼을 그룹화한 결과에 조건을 건다.
- WHERE랑 HAVING을 헷깔리는 경우가 많은데 WHERE는 그룹화 하기 전이고, HAVING은 그룹화 후에 조건이다.
컬럼 그룹화
SELECT 컬럼 FROM 테이블 GROUP BY 그룹화할 컬럼;
조건 처리 후에 컬럼 그룹화
SELECT 컬럼 FROM 테이블 WHERE 조건식 GROUP BY 그룹화할 컬럼;
컬럼 그룹화 후에 조건 처리
SELECT 컬럼 FROM 테이블 GROUP BY 그룹화할 컬럼 HAVING 조건식;
조건 처리 후에 컬럼 그룹화 후에 조건 처리
SELECT 컬럼 FROM 테이블 WHERE 조건식 GROUP BY 그룹화할 컬럼 HAVING 조건식;
ORDER BY가 존재하는 경우
SELECT 컬럼 FROM 테이블 [WHERE 조건식]
GROUP BY 그룹화할 컬럼 [HAVING 조건식] ORDER BY 컬럼1 [, 컬럼2, 컬럼3 ...];
| id | type | name |
|---|
| 1 | 1 | 이성계 |
| 2 | 1 | 장보고 |
| 3 | 2 | 왕건 |
| 4 | 2 | 박혁거세 |
| 5 | 3 | 주몽 |
| 6 | 3 | 온조 |
| 7 | 4 | 대조영 |
type 그룹화하여 name 갯수 조회 (컬럼 그룹화)
SELECT type, COUNT(name) AS cnt
FROM MEMBER GROUP BY type;
type 1 초과인, type 그룹화하여 name 갯수 조회 (조건 처리 후 컬럼 그룹화) - where 조건 사용
- 위에서 조건 처리 후 컬럼을 그룹화한다고 하였다. 그러면 Having이 아닌 where조건을 생각해야한다.
SELECT type, COUNT(name) AS cnt FROM MEMBER
WHERE type > 1 GROUP BY type;
- type 1 초과인, type 그룹화하여 name 갯수 조회🔽 type 1은 제외 된 것을 볼 수 있다.
type 그룹화하여 name 갯수를 가져온 후, 그 중에 갯수가 2개 이상인 데이터 조회 (조건 처리 후에 컬럼 그룹화 후에 조건 처리) - Having 조건 사용
- 아래의 SQL문에서 중요한 점은 HAVING에서의 조건절에서 사용한 컬럼을 잘보아야한다. 컬럼의 그룹화 후에 진행되는 조건이 바로 Having이기 때문에 Having의 조건에서 cnt 라고 알리아스로 설정한 컬럼명을 사용할 수 있다.
SELECT type, COUNT(name) AS cnt FROM MEMBER
GROUP BY type HAVING cnt >= 2;
- type 그룹화하여 name 갯수를 가져온 후, 그 중에 갯수가 2개 이상인 데이터 조회 🔽
type 1 초과인, type 그룹화하여 name 갯수를 가져온 후, 그 중에 갯수가 2개 이상인 데이터 조회 (조건 처리 후에 컬럼 그룹화 후에 조건 처리) - Where와 Having 사용
- 다음의 SQL은 그룹화하기 전의 조건과 후의 조건이 둘다 사용된다.
SELECT type, COUNT(name) AS cnt FROM MEMBER WHERE type > 1 GROUP BY type HAVING cnt >= 2;
- type 1 초과인, type 그룹화하여 name 갯수를 가져온 후, 그 중에 갯수가 2개 이상인 데이터 조회 테이블 🔽
Group by : 각 그룹에서 최신 데이터 가져오기
만약에 다음과 같은 SQL이 있다
select * from member group by type;
| id | type | name |
|---|
| 1 | 1 | 이성계 |
| 3 | 2 | 왕건 |
| 5 | 3 | 주몽 |
| 7 | 4 | 대조영 |
그럼 위의 테이블의 결과와 같이 그룹화 된것의결과 집합에서 그룹의 첫 번째 레코드를 반환하게 된다.
만약 그룹화한 값에서 가장 마지막 값을 얻고 싶다면 ?
SELECT *
FROM MEMBER WHERE id IN (
SELECT MAX(id) FROM MEMBER GROUP BY type
);
- 위와 같이 sql구문을 사용한다면 아래와 같이 그룹화 된값에 가장 최신 값을 얻을 수 있다.
| id | type | name |
|---|
| 2 | 1 | 장보고 |
| 4 | 2 | 박혁거세 |
| 6 | 3 | 온조 |
| 7 | 4 | 대조영 |