4 분 소요

LIMIT: 결과 데이터 수 제한

LIMIT은 출력될 데이터의 수를 제한시킨다.

SELECT 필드명 FROM 테이블명 LIMIT 개수

문법 구조

SELECT * FROM site_users LIMIT 3;

예제 1-1

+-----------+--------------+--------------+---------+-----------------+---------------+
| member_id | sign_up_date | class_number | mileage | username        | aver_purchase |
+-----------+--------------+--------------+---------+-----------------+---------------+
|         1 | 2023-10-23   |            1 |    1549 | pcopozio0       |           616 |
|         2 | 2024-01-09   |            4 |    2712 | eszanto1        |          NULL |
|         3 | 2023-08-15   |            5 |    1129 | jmatuszkiewicz2 |           855 |
+-----------+--------------+--------------+---------+-----------------+---------------+

예제 1-1 실행결과

다음과 같은 형태로도 사용할 수 있다.

LIMIT 시작위치, 개수
LIMIT 개수 OFFSET 시작위치
-- 위 두 구문은 서로 똑같다. 

위 구문은 시작 위치로부터 몇 개만 추출하여 보여주고자 할 때 사용한다. 참고로 여기서의 시작위치는 0번부터 시작한다. 따라서 만약 member_id가 1~3인 정보만 보려고 한다면 다음과 같이 작성해야 한다.

SELECT * FROM site_users LIMIT 0, 3;
SELECT * FROM site_users LIMIT 3 OFFSET 0;

예제 1-2

+-----------+--------------+--------------+---------+-----------------+---------------+
| member_id | sign_up_date | class_number | mileage | username        | aver_purchase |
+-----------+--------------+--------------+---------+-----------------+---------------+
|         1 | 2023-10-23   |            1 |    1549 | pcopozio0       |           616 |
|         2 | 2024-01-09   |            4 |    2712 | eszanto1        |          NULL |
|         3 | 2023-08-15   |            5 |    1129 | jmatuszkiewicz2 |           855 |
+-----------+--------------+--------------+---------+-----------------+---------------+

예제 1-2 실행결과

LIMIT 뒤에 n이라는 숫자 하나만 적으면 이는 LIMIT 0, n 을 뜻하게 된다.

GROUP BY : 데이터를 그룹으로 묶는다

GROUP BY 절은 여러 데이터들을 하나의 그룹으로 묶는 역할을 한다. 주로 그룹별 합산, 평균 등을 내기 위해 Aggregation function과 함께 사용할 때 쓰인다.

다음은 클래스별 마일리지에 대한 합계 및 평균을 보려는 쿼리문이다. 먼저 GROUP BY를 사용하지 않았을 때이다.

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users;

예제 2-1

+--------------+--------------+--------------+
| class_number | SUM(mileage) | AVG(mileage) |
+--------------+--------------+--------------+
|            1 |        59130 |    2956.5000 |
+--------------+--------------+--------------+

예제 2-1 실행결과

클래스별 각각의 마일리지 합계 및 평균을 보고 싶었으나 위 결과에서는 결과가 단 하나만 나왔다. 이는 합계 및 평균 연산이 모든 데이터들에 행해졌다는 뜻이다. 즉, 클래스별로 그룹화하지 않고 사용했기에 이런 문제가 나타난 것이다.

이제 원래 의도를 위해 GROUP BY 절을 사용해보겠다.

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
GROUP BY class_number;

예제 2-2

+--------------+--------------+--------------+
| class_number | SUM(mileage) | AVG(mileage) |
+--------------+--------------+--------------+
|            1 |        12963 |    2592.6000 |
|            2 |        13070 |    3267.5000 |
|            3 |         6028 |    3014.0000 |
|            4 |        12809 |    3202.2500 |
|            5 |        14260 |    2852.0000 |
+--------------+--------------+--------------+

예제 2-2 실행결과

원래 의도되었던 대로 클래스별 각각의 마일리지 합계 및 평균을 구하였다.

ORDER BY와 마찬가지로, GROUP BY 뒤에는 그룹을 지정한 기준을 여러 개 지정할 수 있다. 이 역시 1차 기준, 2차 기준, … 순으로 그룹화가 되는 것이다.

GROUP BY 필드1, 필드2, 필드3, ...

HAVING 조건문 : 그룹화된 데이터에 대한 조건

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
GROUP BY class_number
HAVING class_number <= 3;

예제 3-1

+--------------+--------------+--------------+
| class_number | SUM(mileage) | AVG(mileage) |
+--------------+--------------+--------------+
|            1 |        12963 |    2592.6000 |
|            2 |        13070 |    3267.5000 |
|            3 |         6028 |    3014.0000 |
+--------------+--------------+--------------+

예제 3-1 실행결과

HAVING 조건문은 GROUP BY를 통해 얻은 결과에 대해 조건을 지정하여 해당 조건을 만족하는 데이터만 추출할 수 있게 해주는 키워드이다. HAVING 절은 꼭 쓰지 않아도 되나, 만약 사용한다면 반드시 앞에 GROUP BY 키워드가 사용되어야 한다.

또한 HAVING 조건문은 Aggregation function과 함께 사용할 수 있다.

Aggregation function은 WHERE절과 함께 사용할 수 없다. 다음은 클래스별 마일리지 합계와 평균 결과에서 평균이 3000이상인 클래스만 추출하려고 WHERE절을 사용한 쿼리이다.

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
WHERE AVG(mileage) >= 3000
GROUP BY class_number;

예제 3-2

ERROR 1111 (HY000): Invalid use of group function

예제 3-2 실행결과

Aggregation function인 AVG() 함수를 WHERE절에 사용하니 에러가 뜬 모습이다. WHERE절은 한 번에 한 레코드에 대해서만 검사하는데, 집합 함수는 여러 데이터들을 묶어 계산해야 하기 때문에 수가 맞지 않아 실행되지 않는 것이다.

위 예제를 HAVING절로 바꿔 작성해보자.

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
GROUP BY class_number
HAVING AVG(mileage) >= 3000;

예제 3-3

+--------------+--------------+--------------+
| class_number | SUM(mileage) | AVG(mileage) |
+--------------+--------------+--------------+
|            2 |        13070 |    3267.5000 |
|            3 |         6028 |    3014.0000 |
|            4 |        12809 |    3202.2500 |
+--------------+--------------+--------------+

예제 3-3 실행결과

잘 작동하는 것을 볼 수 있다.

다음은 아까와 같이 각 클래스별 마일리지의 합계 및 평균을 구하는데, 이번에는 클래스 넘버가 1인 데이터는 제외하는 쿼리문이다.

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
WHERE class_number != 1
GROUP BY class_number;

SELECT
  class_number,
  SUM(mileage),
  AVG(mileage)
FROM site_users
GROUP BY class_number
HAVING class_number != 1;

예제 3-4

+--------------+--------------+--------------+
| class_number | SUM(mileage) | AVG(mileage) |
+--------------+--------------+--------------+
|            2 |        13070 |    3267.5000 |
|            3 |         6028 |    3014.0000 |
|            4 |        12809 |    3202.2500 |
|            5 |        14260 |    2852.0000 |
+--------------+--------------+--------------+

예제 3-4 실행결과

위 두 쿼리문 모두 똑같은 결과를 보여준다. 그런데 차이점은 하나는 WHERE절을, 다른 하나는 HAVING 절을 사용했다는 것이다. GROUP BY와 HAVING 절을 같이 사용하는 경우, GROUP BY를 통해 테이블 내 전체 데이터를 그룹화한다. 그룹화된 데이터 묶음에 대해 HAVING 조건문이 실행된다. GROUP BY를 통해 그룹화될 때 필요없는 클래스 넘버 1의 데이터도 같이 그룹화되고 HAVING 절에서야 결과에서 제외되는 방식이다. 반면, WHERE절을 사용할 경우, GROUP BY 보다 WHERE 절이 먼저 실행되어 불필요한 데이터가 먼저 제거된다. 불필요한 데이터가 제거된 후 남은 나머지 데이터들에 대해서만 그룹화가 진행되는 방식이다. 따라서 이론상으로는 GROUP BY 사용 시 WHERE절과 같이 사용하는 것이 HAVING절보다 더 빠르다고 볼 수 있다.

물론 집합 함수를 조건문에 사용한다면 HAVING 절만 사용할 수 있다는 걸 잊지말자.


References

[1] 에이콘아카데미(강남) 강의

[2] 우재남, “혼자 공부하는 SQL”, (한빛미디어, 2021)

[3] [SQL 첫걸음] 11. 결과 행 제한하기 - LIMIT

[4] WHERE vs HAVING 성능 차이

오라클공부 317. HAVING 절과 WHERE 절의 성능 차이

[5] WHERE vs HAVING 성능 차이 (2)

SQL 기초 및 PLSQL 실무 강좌 자료 HAVING 절과 WHERE 절의 성능 차이

This content is licensed under CC BY-NC 4.0

댓글남기기