GROUP BY 에 있을 줄 알았던 HAVING 절이 SELECT 문서에 있더군요.
MySQL에서 HAVING 절을 제대로 이해하지 못해서 한참 헤맸던 경험을 공유하고자 합니다. 저와 같은 실수를 다른 분들이 하지 않길 바라며, 공식 문서를 참고하시고 HAVING 절의 올바른 사용법을 정리했습니다.
첫번째로 GROUP BY 와 HAVING 을 쓰기위해서는 실행 작동 순서부터 잘 알아야 합니다.
1. 조회하는 테이블을 확인
2. 데이터 조건 확인
3. 그룹화
4. 그룹 조건
5. 위 처리한 데이터를 어떤 열에 출력할지 선택
6. 정렬
내가 4일 동안 HAVING 절에 고생한 이유? 예를 들어서 아래와 같은 SQL 문법을 작성했을 경우
SELECT
name,
a.max_money
FROM
player p
GROUP BY name
HAVING MAX(p.money) = (
SELECT
MAX(p2.money) as max_money
FROM player p2
WHERE p.money = MAX(p2.money)
) a
HAVING 절은 BOOLEAN 값을 반환해야 하지만, 위 쿼리에서는 HAVING 절 내부에서 서브쿼리를 사용하여 하나의 값을 비교하려고 했습니다.
서브쿼리가 HAVING이 기대하는 TRUE 또는 FALSE가 아니라 스칼라 값(숫자) 을 반환하기 때문에 오류가 발생합니다.
예를 들어서 아래와 같은 SQL 문법을 작성했을 경우
SELECT
name,
part,
SUM(money)
FROM
player p
GROUP BY part
HAVING IF ( SUM(money) IS NULL, 0, SUM(money) )
이것도 문제가 생깁니다.
의도하는 바 : SUM(money) 가 NULL 이라면 0으로 치환, 아니라면 SUM(money)로 치환
물론 SELECT 절에 그냥 작성할 수 있습니다.
저렇게 작성했다고 했을 때, 결과는 다음과 같이 나오게 됩니다.
NULL 은 부분은 출력되지 않는다.
공식문서 : Boolean
HAVING 은 Boolean 을 반환한다고 했습니다. 근데 SUM(money) 가 Null 이라고 0 으로 치환하면
결과는 0 또는 SUM(money) ?
boolean reuslt = 0 or SUM(money) ????
공식문서에서 볼 수 있듯, 0은 false 입니다.
HAVING 에서 false는 결과를 출력하지 않습니다.
IF 절로 NULL 을 0으로 바꾸면 결과를 출력하지 않습니다.
HAVING IF ( SUM(money) IS NULL, 0, 0 )
예를 들어,
HAVING IF(SUM(money) IS NULL, 0, SUM(money))이 0일 경우 FALSE가 되어 해당 그룹이 제외된다는 점을 강조할 수 있습니다.
+추가적으로 설명드리지만, 그냥SELECT에서 사용해도 되지만 왜 HAVING 절에 사용했냐면... 제약조건이 반드시(무조건) 으로서브쿼리,GROUP BY,HAVING을 사용해라 였기 때문에 하다보니까 이런 사실을 알아냈습니다.
- 결론: 새롭게 배운 것들
HAVING절은 그룹화된 데이터에 대한 논리 평가를 수행한다.
예를 들어서, 언제는 FROM 절에 테이블을 반환하기 위한 형태로, 언제는 boolean 형태로 등등HAVING절 내부에서0이 되면 결과가 제외된다.- 서브쿼리는
HAVING절에서BOOLEAN평가가 가능해야 한다. 그렇지 않으면 WHERE 또는 JOIN으로 해결해야 한다.- 제가 4일간 삽질한 것 헛된 것이 아닙니다. 몰랐던 사실을 알게 되어서 축복이라고 생각합니다.