지난 며칠 동안 SQL 문제풀이를 하면서 학습한 내용들을 정리했습니다.
1. WHERE vs. HAVING
둘 다 필터링을 하지만, 적용되는 시점이 다릅니다.
WHERE: 그룹화 전(Before), 개별 행을 필터링합니다.HAVING: 그룹화 후(After),SUM(),COUNT()등 집계 함수의 결과로 만들어진 그룹을 필터링합니다. 그리고,MySQL에서는Having을 전체 결과를 하나의 그룹으로 간주하여 단독으로 사용할 수도 있습니다.
2. 동적으로 그룹을 만들기
가격을 10,000원 단위로 묶는 등, 정해진 구간별로 그룹화할 때 유용한 방법을 학습했습니다. 최대값을 미리 알기 어려운 경우 사용할 수 있습니다.
-
가격대별 상품 수 구하기:
FLOOR(버림) 함수를 이용해 가격대를 동적으로 생성하고 그룹화합니다.SELECT FLOOR(PRICE / 10000) * 10000 AS PRICE_GROUP, COUNT(PRODUCT_ID) AS PRODUCTS FROM PRODUCT GROUP BY PRICE_GROUP ORDER BY PRICE_GROUP ASC;FLOOR(PRICE / 10000):- 모든 상품의
PRICE를 10,000으로 나눕니다. (예:25000->2.5,9500->0.95) FLOOR()함수로 소수점 이하를 버립니다. (예:2.5->2,0.95->0)
- 모든 상품의
... * 10000:- 버림 처리된 값에 다시 10,000을 곱해 각 가격대의 시작점(가격 그룹)을 만듭니다. (예:
2->20000,0->0) - 이
PRICE_GROUP은 최대 가격에 상관없이 모든 가격에 대해 동적으로 생성됩니다.
- 버림 처리된 값에 다시 10,000을 곱해 각 가격대의 시작점(가격 그룹)을 만듭니다. (예:
GROUP BY PRICE_GROUP:- 동일한
PRICE_GROUP값을 가진 상품들을 하나의 그룹으로 묶습니다.
- 동일한
COUNT(PRODUCT_ID):- 그룹별로 묶인 상품의 개수를 셉니다.
-
MySQL에서GROUP BY절에서SELECT에서 정의한 별칭 사용이 가능한 이유- 보통 다음과 같이 SQL은 실행 순서를 가집니다.
FROM→WHERE→GROUP BY→HAVING→SELECT→DISTINCT→ORDER BY→LIMIT
- 따라서
SELECT보다 먼저 실행되는GROUP BY에서는 별칭을 사용할 수 없어야 합니다. 그러나,MySQL에서는GROUP BY를 실행하기 위해 내부적으로SELECT에 정의된 별칭과 관련된 부분을 먼저 참조하여 계산합니다. 따라서SELECT에서 정의한 별칭을 사용할 수 있습니다. 모든 데이터베이스 벤더에서 지원하는 것은 아닙니다. HAVING에서도 사용할 수 있으며WHERE에서는 사용할 수 없습니다.
- 보통 다음과 같이 SQL은 실행 순서를 가집니다.
3. IN 연산자 vs OR 반복
컬럼의 값이 목록에 있는 정확한 값과 일치하는지 확인하는 경우에는 여러 OR 조건보다 IN (...)을 사용하는 것이 가독성과 성능 모두에서 유리합니다.
SELECT
ANIMAL_ID,
NAME,
SEX_UPON_INTAKE
FROM
ANIMAL_INS
WHERE
NAME IN ('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty')
ORDER BY
ANIMAL_ID ASC;
4. CASE 문 단순화
CASE는 순서대로 평가되므로, NULL을 먼저 처리하거나 ELSE를 활용해 불필요한 조건을 줄일 수 있습니다.
- 개선 전: 조건이 중복될 수 있음
CASE
WHEN OUT_DATE <= '2022-05-01' THEN '출고완료'
WHEN OUT_DATE > '2022-05-01' THEN '출고대기'
ELSE '출고미정'
END
- 개선 후:
NULL을 먼저 처리하고, 순차 평가를 이용해 마지막 조건을ELSE로 단순화
CASE
WHEN OUT_DATE IS NULL THEN '출고미정'
WHEN OUT_DATE <= '2022-05-01' THEN '출고완료'
ELSE '출고대기'
END