GROUP BY
는 MySQL에서 데이터를 그룹화하여 특정 기준에 따라 요약된 결과를 얻을 때 사용됩니다. 대규모 데이터를 처리하거나 집계 연산을 할 때 유용하게 쓰이는 구문이며, 다양한 집계 함수(COUNT
, SUM
, AVG
, MIN
, MAX
등)와 함께 자주 사용됩니다. 이번 글에서는 GROUP BY
의 기본 개념부터 고급 사용법까지 단계별로 살펴보고, 사용 시 주의할 점과 최적화 방법에 대해 설명합니다.
본격적으로 들아기전에 예시 테이블을 생성 해보도록 하겠습니다.
CREATE TABLE sales (
id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(255),
sale_date DATE,
quantity INT,
total_price DECIMAL(10, 2)
);
INSERT INTO sales (product_name, sale_date, quantity, total_price) VALUES
('Laptop', '2024-01-10', 3, 3000.00),
('Laptop', '2024-01-15', 2, 2000.00),
('Phone', '2024-01-10', 5, 2500.00),
('Phone', '2024-02-10', 3, 1500.00),
('Tablet', '2024-01-20', 4, 1600.00),
('Tablet', '2024-02-05', 1, 400.00);
1. GROUP BY
의 기본 개념
GROUP BY
는 쿼리의 결과를 지정한 열(Column)의 값에 따라 그룹화합니다. 예를 들어, 데이터베이스에서 판매 내역을 관리하는 테이블이 있을 때, 각 제품별로 판매된 총 금액을 계산하고 싶다면 GROUP BY
를 사용할 수 있습니다.
SELECT product_name, SUM(total_price)
FROM sales
GROUP BY product_name;
위 쿼리는 sales
테이블에서 product_name
을 기준으로 그룹을 나누고, 각 그룹에 대해 total_price
의 합계를 반환합니다.
2. GROUP BY
와 집계 함수
GROUP BY
는 일반적으로 집계 함수와 함께 사용됩니다. 집계 함수는 그룹화된 데이터에 대해 연산을 수행하여 요약된 정보를 제공합니다. MySQL에서 자주 사용되는 집계 함수는 다음과 같습니다.
COUNT()
: 그룹 내 행(row)의 개수를 계산합니다.SUM()
: 그룹 내 값들의 합계를 계산합니다.AVG()
: 그룹 내 값들의 평균을 계산합니다.MIN()
: 그룹 내 최소값을 반환합니다.MAX()
: 그룹 내 최대값을 반환합니다.
예시:GROUP BY
는 다양한 집계 함수와 함께 사용됩니다. 예를 들어, SUM()
외에도 COUNT()
함수는 각 그룹의 행 개수를 계산하며, AVG()
함수는 평균 값을 계산합니다.
다음 쿼리는 제품별로 총 판매 수량과 평균 판매 금액을 반환합니다.
SELECT product_name, SUM(quantity) AS total_quantity, AVG(total_price) AS avg_price
FROM sales
GROUP BY product_name;
3. HAVING
절과 GROUP BY
GROUP BY
를 사용할 때, 결과를 필터링하려면 HAVING
절을 사용할 수 있습니다. HAVING
절은 GROUP BY
로 그룹화된 데이터에 대한 조건을 설정하는데, 이는 WHERE
절과 유사하지만 GROUP BY
이후에 집계 함수 결과를 필터링할 수 있다는 점에서 다릅니다.
SELECT product_name, SUM(total_price) AS total_sales
FROM sales
GROUP BY product_name
HAVING SUM(total_price) > 3000;
이 쿼리는 총 판매 금액이 3000을 초과하는 제품만 반환합니다. 결과는 다음과 같습니다.
4. GROUP BY
와 정렬
GROUP BY
와 함께 ORDER BY
를 사용하여 그룹화된 결과를 정렬할 수 있습니다. 일반적으로 ORDER BY
는 그룹화된 열이나 집계 함수의 결과를 기준으로 정렬됩니다.
예를 들어, 총 판매 금액에 따라 제품을 내림차순으로 정렬하려면 다음과 같은 쿼리를 사용할 수 있습니다.
SELECT product_name, SUM(total_price) AS total_sales
FROM sales
GROUP BY product_name
ORDER BY total_sales DESC;
5. GROUP BY
에서 다중 열 그룹화
MySQL에서 GROUP BY
는 다중 열을 기준으로 그룹화할 수 있습니다. 예를 들어, 제품명과 판매 날짜를 기준으로 그룹화하여 월별 제품 판매 내역을 요약할 수 있습니다.
SELECT product_name, MONTH(sale_date) AS sale_month, SUM(quantity) AS total_quantity
FROM sales
GROUP BY product_name, sale_month;
6. GROUP BY
의 성능 최적화
GROUP BY
는 데이터베이스 성능에 영향을 미칠 수 있습니다. 특히 대용량 데이터를 다룰 때는 효율적인 쿼리 작성을 통해 성능을 최적화해야 합니다. 이를 위해 몇 가지 팁을 제시합니다.
- 인덱스 사용:
GROUP BY
에 사용되는 열에 인덱스를 생성하면 성능이 향상됩니다. 인덱스는 데이터 검색을 빠르게 하여 쿼리 속도를 높여줍니다. CREATE INDEX idx_product_name ON sales(product_name);
- 임시 테이블 사용: 큰 테이블의 경우
GROUP BY
의 중간 결과를 임시 테이블에 저장하면 성능이 개선될 수 있습니다.
CREATE TEMPORARY TABLE temp_sales AS
SELECT product_name, sale_date, quantity, total_price
FROM sales;
- 적절한 인덱스 설계: 자주 사용하는 열에 대해 복합 인덱스를 생성하여 성능을 향상시킬 수 있습니다.
CREATE INDEX idx_product_sale ON sales(product_name, sale_date);
7. GROUP BY
사용 시 주의사항
GROUP BY
를 사용할 때 주의해야 할 몇 가지 사항이 있습니다.
- SELECT 절에서 비집계 열: MySQL에서
GROUP BY
를 사용할 때는 집계되지 않은 열을SELECT
절에 포함시키면 에러가 발생할 수 있습니다. 모든 비집계 열은 반드시GROUP BY
에 포함되어야 합니다. 그렇지 않으면 의도하지 않은 결과를 초래할 수 있습니다.올바른 사용 예시는 다음과 같습니다.
-- 올바른 예시
SELECT product_name, sale_date, SUM(quantity)
FROM sales
GROUP BY product_name, sale_date;
-- 잘못된 예시
SELECT product_name, sale_date, SUM(quantity)
FROM sales
GROUP BY product_name; -- sale_date는 포함되지 않음
- NULL 값 처리:
GROUP BY
는NULL
값을 하나의 그룹으로 간주합니다. 따라서,NULL
값을 포함한 열을 기준으로 그룹화하면 하나의NULL
그룹이 생성됩니다.
8. 실전 예시: 월별 판매 내역 요약
다음 쿼리는 월별로 제품 판매 내역을 요약하고, 매출 순으로 정렬하는 예시입니다.
SELECT product_name, MONTH(sale_date) AS sale_month, SUM(quantity) AS total_quantity, SUM(total_price) AS total_revenue
FROM sales
GROUP BY product_name, sale_month
ORDER BY total_revenue DESC;
9. 결론
이번 글에서는 MySQL에서 GROUP BY
의 기본 개념부터 고급 사용법까지 살펴보았습니다. GROUP BY
는 데이터를 요약하고 집계하는 데 필수적인 구문으로, 다양한 집계 함수와 함께 강력한 기능을 발휘합니다. 그러나 성능 문제를 방지하려면 적절한 인덱스 설정과 최적화 전략이 필요하며, 사용 시 집계되지 않은 열에 주의해야 합니다.
'DataBase' 카테고리의 다른 글
MySQL에서 복합 유니크 인덱스: 다수의 인덱스와 하나의 인덱스를 비교하여 최적의 설계 방식 찾기 (0) | 2024.10.28 |
---|---|
MySQL 파티셔닝(Partitioning)의 기본 개념과 필요성 (0) | 2024.10.26 |
MySQL에서 DISTINCT의 정의 및 사용법 (0) | 2024.10.24 |
MySQL - EXISTS 함수 (0) | 2024.10.21 |
MySQL - COUNT와 EXISTS 성능 비교 및 최적화 고민 (0) | 2024.10.21 |