이미지 로딩 중...

SQL 집계 함수 완벽 가이드 실무 활용법 - 슬라이드 1/7
A

AI Generated

2025. 11. 22. · 4 Views

SQL 집계 함수 완벽 가이드 실무 활용법

SQL의 집계 함수(COUNT, SUM, AVG, MIN, MAX)를 초급 개발자도 쉽게 이해할 수 있도록 설명합니다. 실무에서 자주 사용하는 데이터 집계 방법과 NULL 처리, 함수 조합 사용법까지 상세하게 다룹니다.


목차

  1. COUNT로_행_개수_세기
  2. SUM으로_합계_계산
  3. AVG로_평균_구하기
  4. MIN_MAX로_최소_최대값_찾기
  5. NULL_값이_집계에_미치는_영향
  6. 집계_함수_조합_사용하기

1. COUNT로_행_개수_세기

시작하며

여러분이 쇼핑몰을 운영하는데 오늘 하루 동안 몇 명의 고객이 주문했는지 알고 싶을 때 어떻게 하실 건가요? 일일이 손으로 세시겠어요?

주문이 10개면 괜찮지만 1000개라면요? 바로 이럴 때 필요한 것이 COUNT 함수입니다.

COUNT는 마치 자동 계수기처럼 데이터베이스에서 행의 개수를 빠르게 세어주는 함수예요. 실무에서는 회원 수 집계, 일일 주문 건수 파악, 카테고리별 상품 수 확인 등 정말 많은 곳에 사용됩니다.

개요

간단히 말해서, COUNT 함수는 테이블에서 조건에 맞는 행(row)의 개수를 세어주는 함수입니다. 왜 이 함수가 필요한지 생각해볼까요?

만약 여러분이 운영하는 온라인 서점에 책이 몇 권 등록되어 있는지, 오늘 가입한 회원이 몇 명인지 알아야 한다면 매번 손으로 세는 건 비효율적이겠죠. COUNT를 사용하면 수십만 건의 데이터도 순식간에 집계할 수 있습니다.

기존에는 애플리케이션 코드에서 모든 데이터를 가져와서 반복문으로 세었다면, 이제는 데이터베이스에서 직접 COUNT로 빠르게 계산할 수 있습니다. COUNT의 핵심 특징은 세 가지입니다.

첫째, COUNT(*)는 NULL을 포함한 모든 행을 세고, 둘째, COUNT(컬럼명)은 해당 컬럼이 NULL이 아닌 행만 세며, 셋째, COUNT(DISTINCT 컬럼명)으로 중복을 제거한 고유값의 개수를 셀 수 있습니다. 이러한 특징들이 실무에서 정확한 데이터 분석을 가능하게 합니다.

코드 예제

-- 전체 주문 건수 세기
SELECT COUNT(*) AS total_orders
FROM orders;

-- 배송 완료된 주문만 세기
SELECT COUNT(*) AS completed_orders
FROM orders
WHERE status = 'delivered';

-- NULL이 아닌 리뷰가 달린 상품 개수
SELECT COUNT(review_text) AS reviewed_products
FROM products;

-- 중복 제외한 고객 수 (한 고객이 여러 주문해도 1명으로 카운트)
SELECT COUNT(DISTINCT customer_id) AS unique_customers
FROM orders;

설명

COUNT가 하는 일은 여러분이 지정한 조건에 맞는 데이터의 개수를 세는 것입니다. 마치 마트에서 계산대를 지나가는 상품을 삐삐 찍으며 세는 것과 같아요.

첫 번째로, COUNT(*)는 가장 기본적인 형태로 테이블의 모든 행을 셉니다. 위 코드에서 SELECT COUNT(*) FROM orders는 orders 테이블에 있는 모든 주문 건수를 세어줍니다.

행에 NULL 값이 있든 없든 상관없이 모든 행을 카운트하죠. 이렇게 하는 이유는 전체 데이터의 규모를 파악하기 위함입니다.

두 번째로, WHERE 절과 함께 사용하면 특정 조건에 맞는 데이터만 셀 수 있습니다. WHERE status = 'delivered'를 추가하면 배송 완료된 주문만 집계됩니다.

실무에서는 "오늘 가입한 회원 수", "진행 중인 프로젝트 개수" 같은 특정 상태의 데이터를 세는 데 자주 사용됩니다. 세 번째로, COUNT(컬럼명)을 사용하면 해당 컬럼이 NULL이 아닌 행만 셉니다.

예를 들어 COUNT(review_text)는 리뷰 텍스트가 실제로 작성된 상품만 세어줍니다. 리뷰가 없는(NULL) 상품은 제외되죠.

네 번째로, COUNT(DISTINCT customer_id)는 중복을 제거한 고유한 값의 개수를 셉니다. 한 고객이 10번 주문했어도 1명으로 카운트됩니다.

이는 "실제 구매 고객 수"를 파악할 때 매우 유용합니다. 여러분이 이 함수를 사용하면 대시보드에 표시할 통계 수치를 빠르게 계산할 수 있고, 비즈니스 의사결정에 필요한 데이터를 즉시 확인할 수 있습니다.

특히 WHERE 절과 GROUP BY를 함께 사용하면 카테고리별, 날짜별로 세분화된 집계도 가능합니다.

실전 팁

💡 COUNT()와 COUNT(1)은 성능상 거의 동일하니 가독성 좋은 COUNT()를 사용하세요

💡 NULL 값을 포함할지 말지 신중히 결정하세요 - 회원 수를 셀 때 탈퇴한 회원(NULL)을 포함하면 안 되겠죠?

💡 큰 테이블에서 COUNT(*)는 느릴 수 있으니 WHERE 절로 범위를 제한하거나 인덱스를 활용하세요

💡 정확한 실시간 카운트가 필요 없다면 캐싱을 고려하세요 - 매번 COUNT 쿼리를 날리면 DB 부하가 커집니다

💡 COUNT와 GROUP BY를 함께 사용하면 카테고리별 개수를 한 번에 집계할 수 있어 효율적입니다


2. SUM으로_합계_계산

시작하며

여러분이 온라인 쇼핑몰을 운영하는데 이번 달 총 매출이 얼마인지 알고 싶다면 어떻게 하시겠어요? 주문 하나하나의 금액을 계산기로 더하시겠어요?

이런 문제는 실제 개발 현장에서 매일 발생합니다. 매출 집계, 재고 총량 계산, 사용자별 포인트 합산 등 숫자를 더해야 하는 경우는 정말 많거든요.

바로 이럴 때 필요한 것이 SUM 함수입니다. SUM은 여러분이 지정한 컬럼의 모든 값을 자동으로 더해주는 계산기 같은 함수예요.

개요

간단히 말해서, SUM 함수는 특정 컬럼의 모든 숫자 값을 더해서 총합을 구하는 함수입니다. 왜 이 함수가 필요한지 실무 관점에서 생각해볼까요?

만약 여러분이 1000건의 주문 데이터에서 총 매출을 계산해야 한다면, 애플리케이션에서 모든 데이터를 가져와 반복문으로 더하는 것보다 데이터베이스에서 SUM으로 바로 계산하는 게 훨씬 빠르고 효율적입니다. 특히 일일 매출 리포트, 월별 비용 집계 같은 경우에 매우 유용하죠.

기존에는 모든 행을 SELECT로 가져와서 프로그래밍 언어로 합계를 계산했다면, 이제는 데이터베이스에서 직접 SUM으로 한 줄로 계산할 수 있습니다. SUM의 핵심 특징은 세 가지입니다.

첫째, NULL 값은 자동으로 무시하고 계산합니다. 둘째, 숫자 타입 컬럼에만 사용할 수 있습니다(문자열에는 안 돼요).

셋째, WHERE 절과 함께 사용하면 특정 조건의 데이터만 합산할 수 있습니다. 이러한 특징들이 정확한 재무 보고서와 통계 자료를 만들 수 있게 해줍니다.

코드 예제

-- 전체 주문의 총 매출액
SELECT SUM(total_amount) AS total_revenue
FROM orders;

-- 이번 달 배송 완료된 주문의 매출만 계산
SELECT SUM(total_amount) AS monthly_revenue
FROM orders
WHERE status = 'delivered'
  AND MONTH(order_date) = MONTH(CURRENT_DATE);

-- 특정 고객의 총 구매 금액
SELECT customer_id, SUM(total_amount) AS customer_total
FROM orders
WHERE customer_id = 1001
GROUP BY customer_id;

-- 카테고리별 총 재고 수량
SELECT category, SUM(stock_quantity) AS total_stock
FROM products
GROUP BY category;

설명

SUM이 하는 일은 여러분이 지정한 컬럼의 모든 숫자를 하나하나 더하는 것입니다. 마치 장바구니에 담긴 모든 상품의 가격을 더해서 총 금액을 계산하는 것과 같아요.

첫 번째로, SELECT SUM(total_amount) FROM orders는 orders 테이블의 모든 주문 금액(total_amount)을 더합니다. 만약 주문이 3건이고 금액이 각각 10000원, 20000원, 30000원이라면 결과는 60000원이 되겠죠.

AS total_revenue를 사용해서 결과 컬럼에 의미 있는 이름을 붙여주면 가독성이 좋아집니다. 두 번째로, WHERE 절을 추가하면 특정 조건에 맞는 데이터만 합산할 수 있습니다.

위 코드에서는 배송 완료되고 이번 달에 주문된 것만 더하고 있습니다. 실무에서는 "이번 주 매출", "특정 지역 매출" 같은 세부적인 집계가 필요한 경우가 많은데, 이렇게 WHERE 절로 필터링하면 됩니다.

세 번째로, GROUP BY와 함께 사용하면 그룹별 합계를 구할 수 있습니다. GROUP BY customer_id를 사용하면 고객별로 총 구매 금액을 계산해줍니다.

이는 VIP 고객을 식별하거나 고객 등급을 매기는 데 활용됩니다. 네 번째로, 카테고리별 재고 수량을 합산하는 예제처럼 GROUP BY를 활용하면 한 번의 쿼리로 여러 그룹의 합계를 동시에 계산할 수 있습니다.

이전에는 카테고리마다 별도 쿼리를 날렸다면, 이제는 한 방에 해결되는 거죠. 여러분이 이 함수를 사용하면 재무 보고서 작성 시간을 대폭 단축할 수 있고, 실시간 매출 대시보드를 쉽게 구축할 수 있습니다.

특히 전자상거래, 회계 시스템, 재고 관리 시스템에서는 SUM 없이는 불가능한 기능들이 많습니다.

실전 팁

💡 SUM 결과가 NULL이 나오면 COALESCE(SUM(amount), 0)으로 0으로 바꿔주세요 - 빈 결과를 명확히 표시할 수 있습니다

💡 매우 큰 숫자를 더할 때는 오버플로우를 주의하세요 - BIGINT 타입 사용을 고려하세요

💡 소수점 계산 시 DECIMAL 타입을 사용하면 정확한 금액 계산이 가능합니다 (FLOAT는 부정확할 수 있어요)

💡 GROUP BY와 함께 사용할 때 인덱스가 있으면 성능이 크게 향상됩니다

💡 WHERE 절은 GROUP BY 전에 필터링하고, HAVING 절은 SUM 결과를 필터링할 때 사용하세요


3. AVG로_평균_구하기

시작하며

여러분이 운영하는 앱의 평균 리뷰 점수가 궁금하신가요? 아니면 상품들의 평균 가격대를 알고 싶으신가요?

모든 값을 더한 다음 개수로 나누는 계산을 매번 하시겠어요? 이런 평균 계산은 데이터 분석에서 가장 자주 사용되는 통계 지표 중 하나입니다.

사용자 만족도 측정, 가격 정책 수립, 성과 평가 등 거의 모든 분야에서 필요하죠. 바로 이럴 때 필요한 것이 AVG 함수입니다.

AVG는 자동으로 평균을 계산해주는 똑똑한 함수로, SUM과 COUNT를 합친 것처럼 동작해요.

개요

간단히 말해서, AVG 함수는 특정 컬럼의 모든 값을 더한 후 개수로 나눠서 평균값을 구하는 함수입니다. 왜 이 함수가 필요할까요?

실무에서 평균은 정말 중요한 지표입니다. 예를 들어, 상품 평균 평점이 4.5점인지 2.0점인지에 따라 마케팅 전략이 완전히 달라지겠죠?

직원들의 평균 근속 연수, 평균 주문 금액(AOV), 평균 응답 시간 등 비즈니스 의사결정에 필요한 핵심 지표들이 모두 평균값입니다. 기존에는 SUM으로 합계를 구하고 COUNT로 개수를 센 다음, 애플리케이션에서 나눗셈을 했다면, 이제는 AVG 하나로 데이터베이스에서 바로 계산할 수 있습니다.

AVG의 핵심 특징은 세 가지입니다. 첫째, NULL 값은 자동으로 제외하고 평균을 계산합니다(0이 아니라 아예 제외!).

둘째, 결과는 소수점 값으로 나오므로 필요하면 ROUND 함수로 반올림할 수 있습니다. 셋째, 숫자 타입 컬럼에만 사용 가능합니다.

이러한 특징들이 정확한 통계 분석을 가능하게 합니다.

코드 예제

-- 전체 상품의 평균 가격
SELECT AVG(price) AS average_price
FROM products;

-- 평균을 소수점 둘째 자리까지 반올림
SELECT ROUND(AVG(price), 2) AS average_price
FROM products;

-- 특정 카테고리의 평균 평점
SELECT AVG(rating) AS avg_rating
FROM products
WHERE category = 'electronics';

-- 카테고리별 평균 가격 (GROUP BY 활용)
SELECT category, ROUND(AVG(price), 2) AS avg_price
FROM products
GROUP BY category;

-- NULL이 있을 때 0으로 처리하고 싶다면
SELECT COALESCE(AVG(rating), 0) AS avg_rating
FROM products;

설명

AVG가 하는 일은 모든 값을 더한 후 개수로 나누는 것입니다. 마치 학교에서 시험 점수의 평균을 구하는 것과 똑같아요.

첫 번째로, SELECT AVG(price) FROM products는 products 테이블의 모든 상품 가격을 더한 후, 상품 개수로 나눕니다. 만약 상품이 3개이고 가격이 10000원, 20000원, 30000원이라면 (10000+20000+30000)/3 = 20000원이 결과로 나옵니다.

이렇게 계산하는 이유는 전체 상품의 평균 가격대를 파악하기 위함입니다. 두 번째로, ROUND 함수를 함께 사용하면 소수점 자리를 조정할 수 있습니다.

ROUND(AVG(price), 2)는 평균값을 소수점 둘째 자리까지만 표시합니다. 실무에서 가격은 보통 원 단위까지만 필요하니까 ROUND(AVG(price), 0)으로 정수로 만들 수도 있죠.

세 번째로, WHERE 절을 추가하면 특정 조건의 데이터만으로 평균을 계산합니다. 위 예제에서는 전자제품 카테고리의 평균 평점만 계산하고 있습니다.

"특정 기간의 평균 매출", "특정 지역의 평균 나이" 같은 세부 통계를 낼 때 유용합니다. 네 번째로, GROUP BY와 함께 사용하면 그룹별 평균을 한 번에 계산할 수 있습니다.

카테고리별 평균 가격을 구하면 어떤 카테고리가 고가인지, 저가인지 한눈에 파악할 수 있습니다. 이는 가격 정책 수립이나 재고 전략에 활용됩니다.

다섯 번째로, NULL 처리가 중요합니다. AVG는 NULL을 제외하고 계산하는데, 만약 모든 값이 NULL이면 결과도 NULL입니다.

이럴 때 COALESCE를 사용하면 NULL 대신 0을 반환할 수 있어요. 여러분이 이 함수를 사용하면 상품 가격 정책을 데이터 기반으로 수립할 수 있고, 사용자 만족도를 정량적으로 측정할 수 있습니다.

특히 A/B 테스트 결과 분석, 성과 측정, 품질 관리에서 평균값은 필수적인 지표입니다.

실전 팁

💡 평균값만으로는 부족할 수 있으니 MIN, MAX도 함께 확인해서 데이터의 분포를 파악하세요

💡 이상치(outlier)가 평균을 왜곡할 수 있으니 중앙값(MEDIAN)도 함께 보는 게 좋습니다

💡 정수 컬럼의 평균을 구할 때 소수점이 잘릴 수 있으니 CAST로 DECIMAL로 변환 후 계산하세요

💡 HAVING 절로 AVG 결과를 필터링할 수 있습니다 - "평균 평점이 4.0 이상인 카테고리만" 같은 조건에 사용

💡 NULL이 많은 컬럼은 평균이 부정확할 수 있으니 COUNT로 NULL이 아닌 값의 개수도 함께 확인하세요


4. MIN_MAX로_최소_최대값_찾기

시작하며

여러분이 쇼핑몰에서 가장 비싼 상품과 가장 저렴한 상품을 찾아야 한다면 어떻게 하시겠어요? 모든 상품을 하나하나 비교하면서 찾으시겠어요?

이런 문제는 실제 개발에서 정말 자주 발생합니다. 최저가/최고가 찾기, 가장 오래된/최신 데이터 조회, 최고 점수/최저 점수 확인 등 극값을 찾아야 하는 경우가 많거든요.

바로 이럴 때 필요한 것이 MIN과 MAX 함수입니다. MIN은 가장 작은 값을, MAX는 가장 큰 값을 자동으로 찾아주는 함수로, 마치 자동 정렬 후 첫 번째/마지막 값을 가져오는 것과 같아요.

개요

간단히 말해서, MIN 함수는 컬럼에서 가장 작은 값을, MAX 함수는 가장 큰 값을 찾아주는 함수입니다. 왜 이 함수들이 필요할까요?

실무에서 극값은 중요한 의미를 가집니다. 예를 들어, 최저가 상품을 찾아 할인 행사를 기획하거나, 최고 매출 제품을 분석해서 마케팅 전략을 세우거나, 가장 오래된 미처리 주문을 찾아 우선 처리하는 등의 작업에 필수적입니다.

또한 데이터의 범위(range)를 파악하는 데도 유용하죠. 기존에는 ORDER BY로 정렬한 후 LIMIT 1로 첫 번째 행을 가져왔다면, 이제는 MIN/MAX로 바로 값만 가져올 수 있습니다.

훨씬 간단하고 성능도 좋습니다. MIN과 MAX의 핵심 특징은 네 가지입니다.

첫째, 숫자뿐 아니라 날짜, 문자열에도 사용할 수 있습니다(문자열은 사전 순서). 둘째, NULL 값은 자동으로 무시합니다.

셋째, GROUP BY와 함께 사용하면 그룹별 극값을 구할 수 있습니다. 넷째, WHERE 절로 특정 범위 내에서의 극값을 찾을 수 있습니다.

이러한 특징들이 다양한 비즈니스 시나리오에 활용됩니다.

코드 예제

-- 가장 비싼 상품과 가장 저렴한 상품의 가격
SELECT
    MAX(price) AS highest_price,
    MIN(price) AS lowest_price
FROM products;

-- 카테고리별 최고가와 최저가
SELECT
    category,
    MAX(price) AS max_price,
    MIN(price) AS min_price
FROM products
GROUP BY category;

-- 가장 최근 주문 날짜와 가장 오래된 주문 날짜
SELECT
    MAX(order_date) AS latest_order,
    MIN(order_date) AS oldest_order
FROM orders;

-- 특정 카테고리에서 재고가 가장 많은 수량
SELECT MAX(stock_quantity) AS max_stock
FROM products
WHERE category = 'books';

-- 가격 범위 계산 (최고가 - 최저가)
SELECT
    MAX(price) - MIN(price) AS price_range
FROM products;

설명

MIN과 MAX가 하는 일은 모든 값을 비교해서 가장 작은 값과 가장 큰 값을 찾는 것입니다. 마치 키 순서로 줄을 세웠을 때 맨 앞사람과 맨 뒷사람을 찾는 것과 같아요.

첫 번째로, SELECT MAX(price), MIN(price) FROM products는 상품 테이블에서 가장 비싼 가격과 가장 저렴한 가격을 동시에 찾습니다. 만약 상품 가격이 5000원, 10000원, 15000원이라면 MAX는 15000원, MIN은 5000원을 반환합니다.

이렇게 하는 이유는 상품 가격대의 범위를 한눈에 파악하기 위함입니다. 두 번째로, GROUP BY와 함께 사용하면 각 그룹별로 극값을 찾을 수 있습니다.

카테고리별 최고가와 최저가를 구하면 "의류 카테고리는 5만원50만원, 도서 카테고리는 1만원3만원" 같은 분석이 가능합니다. 이는 카테고리별 가격 정책을 수립하는 데 도움이 됩니다.

세 번째로, 날짜 타입에도 사용할 수 있습니다. MAX(order_date)는 가장 최근 주문 날짜를, MIN(order_date)는 가장 오래된 주문 날짜를 반환합니다.

실무에서는 "마지막 로그인 날짜", "첫 구매 날짜" 같은 정보를 추출할 때 유용하죠. 네 번째로, WHERE 절을 추가하면 특정 조건 내에서의 극값을 찾습니다.

위 예제에서는 책 카테고리에서만 최대 재고 수량을 찾고 있습니다. "이번 달 최고 매출액", "특정 지역의 최저 온도" 같은 세부적인 분석에 활용됩니다.

다섯 번째로, MAX와 MIN을 조합하면 범위(range)를 계산할 수 있습니다. MAX(price) - MIN(price)는 가격의 범위를 알려줍니다.

범위가 크면 상품 가격대가 다양하다는 의미이고, 작으면 가격대가 비슷하다는 의미입니다. 여러분이 이 함수들을 사용하면 가격 비교 서비스를 쉽게 만들 수 있고, 이상치 탐지, 품질 관리, 성과 분석 등 다양한 분야에 활용할 수 있습니다.

특히 대시보드에서 "최고/최저" 지표를 표시할 때 필수적입니다.

실전 팁

💡 문자열에 사용하면 사전 순서로 비교됩니다 - MIN('apple', 'banana')는 'apple'이 됩니다

💡 날짜 타입에서 MAX는 가장 최근 날짜, MIN은 가장 오래된 날짜를 의미합니다

💡 극값을 가진 전체 행을 가져오고 싶다면 서브쿼리를 사용하세요 - WHERE price = (SELECT MAX(price) FROM products)

💡 인덱스가 있으면 MIN/MAX는 매우 빠르게 동작합니다 - 전체 스캔 없이 인덱스의 양 끝만 확인하면 되거든요

💡 MAX/MIN과 GROUP BY를 함께 사용할 때 HAVING 절로 결과를 필터링할 수 있습니다


5. NULL_값이_집계에_미치는_영향

시작하며

여러분이 상품 평점의 평균을 계산하는데, 일부 상품은 아직 평점이 없다면 어떻게 될까요? 그 평점을 0점으로 봐야 할까요, 아니면 아예 계산에서 제외해야 할까요?

이런 문제는 실무에서 정말 중요한 이슈입니다. NULL을 어떻게 처리하느냐에 따라 통계 결과가 완전히 달라질 수 있거든요.

잘못 처리하면 매출 보고서가 부정확해지고, 잘못된 의사결정으로 이어질 수 있습니다. 바로 이럴 때 필요한 것이 NULL 처리에 대한 정확한 이해입니다.

SQL 집계 함수들은 NULL을 특별하게 다루는데, 이를 모르면 예상치 못한 결과가 나올 수 있어요.

개요

간단히 말해서, NULL은 "값이 없음" 또는 "알 수 없음"을 의미하며, 대부분의 집계 함수는 NULL을 자동으로 무시하고 계산합니다. 왜 NULL 처리가 중요할까요?

실무에서 데이터는 완벽하지 않습니다. 고객이 선택 항목을 입력하지 않았거나, 센서가 일시적으로 데이터를 수집하지 못했거나, 아직 처리되지 않은 정보일 수 있죠.

이때 NULL과 0은 완전히 다른 의미입니다. 예를 들어, 평점이 0점인 것과 아직 평점이 없는 것(NULL)은 다르죠.

0점은 "매우 나쁨"이고, NULL은 "아직 평가 안 됨"이니까요. 기존에는 NULL을 어떻게 처리할지 몰라서 애플리케이션 레벨에서 복잡한 조건문을 작성했다면, 이제는 SQL이 자동으로 처리하는 방식을 이해하고 필요할 때만 COALESCE나 IFNULL로 명시적으로 처리하면 됩니다.

NULL 처리의 핵심 특징은 네 가지입니다. 첫째, COUNT(*)는 NULL을 포함하지만 COUNT(컬럼)은 NULL을 제외합니다.

둘째, SUM, AVG, MIN, MAX는 모두 NULL을 무시합니다. 셋째, 모든 값이 NULL이면 결과도 NULL입니다(COUNT 제외).

넷째, COALESCE 함수로 NULL을 다른 값으로 대체할 수 있습니다. 이러한 특징들을 알아야 정확한 데이터 분석이 가능합니다.

코드 예제

-- COUNT(*)는 NULL 포함, COUNT(컬럼)은 NULL 제외
SELECT
    COUNT(*) AS total_products,              -- 모든 행 (5개)
    COUNT(rating) AS rated_products          -- rating이 NULL이 아닌 행 (3개)
FROM products;

-- AVG는 NULL을 제외하고 계산
-- rating이 4, 5, NULL, NULL, 3이라면
-- AVG(rating) = (4+5+3)/3 = 4.0 (NULL 2개는 제외됨)
SELECT AVG(rating) AS average_rating
FROM products;

-- NULL을 0으로 바꾸고 싶다면
SELECT AVG(COALESCE(rating, 0)) AS average_rating
FROM products;

-- NULL 개수 세기
SELECT
    COUNT(*) - COUNT(rating) AS null_count
FROM products;

-- 결과가 NULL일 때 기본값 설정
SELECT COALESCE(SUM(discount_amount), 0) AS total_discount
FROM orders
WHERE status = 'cancelled';  -- 취소 주문이 없으면 NULL 대신 0 반환

설명

NULL이 집계에 미치는 영향을 이해하는 것은 정확한 데이터 분석의 핵심입니다. NULL은 0도 아니고 빈 문자열도 아닌, "값이 없다"는 특별한 상태예요.

첫 번째로, COUNT의 두 가지 형태를 구분해야 합니다. COUNT(*)는 행의 개수를 세는 것이므로 NULL이든 아니든 모든 행을 셉니다.

만약 상품이 5개 있다면 결과는 5입니다. 하지만 COUNT(rating)은 rating 컬럼이 NULL이 아닌 행만 셉니다.

5개 상품 중 3개만 평점이 있다면 결과는 3이 됩니다. 이 차이를 이용하면 COUNT(*) - COUNT(rating)으로 NULL의 개수를 셀 수 있어요.

두 번째로, AVG는 NULL을 계산에서 완전히 제외합니다. 예를 들어 평점이 [4, 5, NULL, NULL, 3]이라면, AVG는 4와 5와 3만 더해서 3으로 나눕니다.

결과는 (4+5+3)/3 = 4.0입니다. NULL을 0으로 보지 않는다는 게 중요합니다.

만약 NULL을 0으로 취급하고 싶다면 AVG(COALESCE(rating, 0))처럼 명시적으로 변환해야 합니다. 세 번째로, SUM도 마찬가지로 NULL을 무시합니다.

[10, 20, NULL, 30]을 SUM하면 60입니다. NULL은 더하기에 포함되지 않아요.

하지만 모든 값이 NULL이라면? 결과도 NULL이 됩니다.

이럴 때 COALESCE(SUM(amount), 0)을 사용하면 NULL 대신 0을 반환할 수 있습니다. 네 번째로, MIN과 MAX도 NULL을 무시합니다.

[5, NULL, 10, NULL, 15]에서 MAX는 15, MIN은 5입니다. NULL은 비교 대상에서 제외되죠.

다섯 번째로, 실무에서 가장 중요한 팁은 "NULL의 의미를 정확히 파악하라"는 것입니다. 만약 평점이 NULL인 상품을 평균 계산에서 제외하고 싶다면 그대로 AVG(rating)을 쓰면 되고, NULL을 0으로 보고 싶다면 COALESCE를 써야 합니다.

어느 쪽이 비즈니스 로직에 맞는지 판단하는 게 중요합니다. 여러분이 이 개념을 이해하면 데이터 품질 문제를 빠르게 파악할 수 있고, 정확한 통계 리포트를 작성할 수 있습니다.

특히 불완전한 데이터를 다룰 때 NULL 처리는 필수적인 기술입니다.

실전 팁

💡 NULL과 0은 다릅니다 - 평점이 0점인 것과 평점이 없는 것은 완전히 다른 의미입니다

💡 COUNT(*)와 COUNT(컬럼)의 차이를 활용해서 데이터 완성도를 측정하세요

💡 COALESCE(값, 기본값) 함수로 NULL을 원하는 값으로 대체할 수 있습니다

💡 WHERE 절에서 NULL을 찾으려면 = NULL이 아니라 IS NULL을 사용해야 합니다

💡 집계 결과가 NULL이 나올 수 있으니 프론트엔드에서 표시할 때 기본값 처리를 해주세요


6. 집계_함수_조합_사용하기

시작하며

여러분이 월별 매출 보고서를 만드는데 총 매출액, 평균 주문 금액, 최고 주문 금액, 총 주문 건수를 모두 보여줘야 한다면 어떻게 하시겠어요? 쿼리를 4번 날리시겠어요?

이런 상황은 실무에서 정말 흔합니다. 대시보드를 만들 때, 리포트를 생성할 때, 데이터 분석을 할 때 여러 지표를 동시에 계산해야 하는 경우가 많거든요.

바로 이럴 때 필요한 것이 집계 함수 조합입니다. 여러 집계 함수를 하나의 쿼리에서 함께 사용하면 성능도 좋고 코드도 간결해져요.

개요

간단히 말해서, 집계 함수 조합은 SELECT 문에서 COUNT, SUM, AVG, MIN, MAX 등 여러 집계 함수를 동시에 사용하는 것입니다. 왜 이 기법이 필요할까요?

실무에서는 하나의 지표만으로는 부족한 경우가 많습니다. 예를 들어, 매출 총액만 보면 주문 건수가 적은데 주문당 금액이 큰 건지, 주문 건수가 많은데 주문당 금액이 작은 건지 알 수 없죠.

여러 지표를 함께 보면 데이터의 전체 그림을 파악할 수 있습니다. 또한 쿼리 한 번으로 여러 값을 가져오면 데이터베이스 부하도 줄고 응답 속도도 빨라집니다.

기존에는 각 지표마다 별도 쿼리를 날렸다면, 이제는 하나의 쿼리로 모든 지표를 한 번에 계산할 수 있습니다. 특히 GROUP BY와 함께 사용하면 그룹별로 여러 통계를 동시에 볼 수 있어 매우 강력합니다.

집계 함수 조합의 핵심 특징은 네 가지입니다. 첫째, 하나의 SELECT 문에 여러 집계 함수를 동시에 사용할 수 있습니다.

둘째, 각 집계 함수는 독립적으로 동작하며 서로 영향을 주지 않습니다. 셋째, GROUP BY와 함께 사용하면 그룹별 다차원 분석이 가능합니다.

넷째, HAVING 절로 집계 결과를 필터링할 수 있습니다. 이러한 특징들이 복잡한 비즈니스 리포트를 간단하게 만들어줍니다.

코드 예제

-- 주문 데이터의 종합 통계
SELECT
    COUNT(*) AS total_orders,                    -- 총 주문 건수
    SUM(total_amount) AS total_revenue,          -- 총 매출액
    AVG(total_amount) AS average_order_value,    -- 평균 주문 금액
    MIN(total_amount) AS min_order,              -- 최소 주문 금액
    MAX(total_amount) AS max_order               -- 최대 주문 금액
FROM orders
WHERE order_date >= '2025-01-01';

-- 카테고리별 상세 통계 (GROUP BY와 조합)
SELECT
    category,
    COUNT(*) AS product_count,
    AVG(price) AS avg_price,
    MIN(price) AS min_price,
    MAX(price) AS max_price,
    SUM(stock_quantity) AS total_stock
FROM products
GROUP BY category;

-- HAVING으로 집계 결과 필터링
SELECT
    customer_id,
    COUNT(*) AS order_count,
    SUM(total_amount) AS total_spent,
    AVG(total_amount) AS avg_order_value
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 5  -- 5번 이상 주문한 고객만
ORDER BY total_spent DESC;

-- 여러 조건의 COUNT 조합
SELECT
    COUNT(*) AS total_products,
    COUNT(CASE WHEN stock_quantity > 0 THEN 1 END) AS in_stock,
    COUNT(CASE WHEN stock_quantity = 0 THEN 1 END) AS out_of_stock,
    AVG(price) AS avg_price
FROM products;

설명

집계 함수 조합이 하는 일은 여러 통계 지표를 한 번에 계산하는 것입니다. 마치 시험을 볼 때 총점, 평균, 최고점, 최저점을 한 번에 계산하는 것과 같아요.

첫 번째로, 기본적인 조합 사용법입니다. SELECT COUNT(*), SUM(total_amount), AVG(total_amount)...처럼 여러 집계 함수를 쉼표로 구분해서 나열하면 됩니다.

각 함수는 독립적으로 동작하므로 서로 영향을 주지 않아요. 위 예제에서는 주문의 총 건수, 총 매출액, 평균 주문 금액, 최소/최대 주문 금액을 한 번에 계산하고 있습니다.

이렇게 하면 쿼리 한 번으로 주문 데이터의 전체 상황을 파악할 수 있죠. 두 번째로, GROUP BY와 함께 사용하면 그룹별로 여러 통계를 동시에 볼 수 있습니다.

카테고리별 상품 수, 평균 가격, 최저/최고가, 총 재고를 한 번에 계산하면 "의류는 상품 50개, 평균 3만원, 최저 1만원, 최고 10만원, 재고 500개" 같은 종합 정보를 얻을 수 있습니다. 이는 카테고리별 비교 분석에 매우 유용합니다.

세 번째로, HAVING 절을 사용하면 집계 결과를 필터링할 수 있습니다. HAVING COUNT(*) >= 5는 주문 건수가 5건 이상인 고객만 선택합니다.

WHERE 절은 집계 전에 필터링하고, HAVING은 집계 후에 필터링한다는 차이가 있어요. 실무에서는 "VIP 고객(총 구매액 100만원 이상)", "인기 상품(리뷰 10개 이상)" 같은 조건에 HAVING을 사용합니다.

네 번째로, CASE WHEN과 조합하면 조건부 집계가 가능합니다. COUNT(CASE WHEN stock_quantity > 0 THEN 1 END)는 재고가 있는 상품만 셉니다.

이렇게 하면 하나의 쿼리로 "전체 상품 수", "재고 있는 상품 수", "재고 없는 상품 수"를 동시에 계산할 수 있어요. 다섯 번째로, 실무 팁입니다.

집계 함수를 조합할 때는 각 함수의 결과에 의미 있는 별칭(AS)을 붙여주세요. total_revenue, avg_order_value 같은 명확한 이름을 사용하면 코드 가독성이 좋아지고, 프론트엔드에서 데이터를 사용할 때도 편리합니다.

여러분이 이 기법을 사용하면 복잡한 대시보드를 간단한 쿼리로 구현할 수 있고, 비즈니스 리포트 생성 시간을 크게 단축할 수 있습니다. 특히 관리자 페이지, 통계 페이지, 분석 도구에서는 집계 함수 조합이 필수적입니다.

실전 팁

💡 너무 많은 집계 함수를 한 쿼리에 넣으면 가독성이 떨어지니 적절히 분리하세요

💡 GROUP BY의 각 그룹마다 모든 집계 함수가 독립적으로 계산됩니다

💡 HAVING 절은 집계 함수의 결과를 필터링할 때, WHERE 절은 집계 전 데이터를 필터링할 때 사용하세요

💡 ORDER BY에서도 집계 함수를 사용할 수 있습니다 - ORDER BY SUM(amount) DESC로 정렬 가능

💡 서브쿼리나 CTE(WITH 절)로 집계 결과를 재사용하면 더 복잡한 분석이 가능합니다


#SQL#COUNT#SUM#AVG#집계함수#SQL,Database,데이터베이스

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

SQL 실전 종합 프로젝트 완벽 가이드

전자상거래 시스템을 직접 구축하면서 배우는 SQL 실전 프로젝트입니다. DB 설계부터 성능 최적화까지, 실무에서 필요한 모든 SQL 기술을 단계별로 마스터할 수 있습니다. 초급 개발자도 따라하기 쉬운 친절한 가이드로 구성되어 있습니다.

실무 데이터 분석 SQL 완벽 가이드

실제 업무에서 자주 사용하는 SQL 데이터 분석 기법을 단계별로 학습합니다. 매출 집계부터 고객 세분화까지, 실전 대시보드 쿼리 작성 방법을 배워보세요.

데이터 모델링과 정규화 완벽 가이드

데이터베이스 설계의 핵심인 데이터 모델링과 정규화를 초급 개발자 눈높이에서 쉽게 설명합니다. ERD 작성부터 제1~3정규형, 정규화의 장단점, 비정규화 전략, 실무 설계 패턴까지 실전에서 바로 활용할 수 있는 노하우를 담았습니다.

트랜잭션과 ACID 원칙 완벽 가이드

데이터베이스의 핵심 개념인 트랜잭션과 ACID 원칙을 초급 개발자도 쉽게 이해할 수 있도록 실무 예제와 함께 설명합니다. 안전한 데이터 처리를 위한 필수 지식을 친근하게 배워보세요.

인덱스와 쿼리 성능 최적화 완벽 가이드

데이터베이스 성능의 핵심인 인덱스를 처음부터 끝까지 배워봅니다. B-Tree 구조부터 실행 계획 분석까지, 실무에서 바로 사용할 수 있는 인덱스 최적화 전략을 초급자도 이해할 수 있게 설명합니다.