본문 바로가기

Development/SQL

통계 값을 구할 때의 기준(GROUP BY)과 정렬(ORDER BY)

들어가며

매일 8강의씩 들을 수 있기 때문인지 교육 2일차에 벌써 2주차 수업에 접어들었다(강의 영상은 평균 10분 이내로 짧지만, 퀴즈와 과제를 해결하다보면 몇 시간으로도 부족하게 느껴진다). 1주차 강의에서는 원하는 데이터를 날것 그대로 가져오는 쿼리문을 다뤄보았다면, 2주차에서는 데이터를 그룹화해서 통계를 구하는 쿼리문을 다루었다.

데이터 통계

넓은 범위에서 데이터 통계는 굉장히 복잡하고 어렵게 느껴질 수 있지만, 좁은 범위에서의 통계는 최댓값, 최솟값, 평균, 합계 정도를 구하는 것으로 매우 쉽고 간단하다.

쿼리문 작성 요령

스파르타코딩클럽에서 쿼리문을 작성할 때 한 가지 요령을 알려주었는데, 그건 바로 쿼리문 작성 순서이다. 개인적으로는 쿼리문이 복잡할수록이 요령을 떠올려보며 차근차근 쿼리문을 작성하는 것이 가장 중요하다고 느꼈다. 이게 무슨 말인지는 간단한 예시를 통해 살펴보도록 하자. 예시에서 사용될 orders 테이블에는 교육과정별 결제 내역이 담겨있는데, 이 데이터를 활용하여 아래와 같이 교육과정별 수강 중인 인원을 구해보도록 하자.

course_title count
웹개발 종합반 ?
앱개발 종합반 ?

👉 orders 테이블 조회

먼저, 아래와 같이 쿼리를 날려서 orders 테이블의 필드를 확인하여 우리가 찾고자 하는 데이터의 필드가 course_title인 것을 확인하자.

SELECT * FROM orders;

👉 교육과정 그룹화

GROUP BY를 통해 course_title을 그룹화한다. GROUP BY는 말 그대로 테이블의 특정 필드를 그룹화하여 통계값을 구할 수 있는 문법이다. 아래 코드를 보면 특정 필드를 그룹화 하였으나, 어떠한 통계(최솟값인지, 최댓값인지 등) 수치를 구할 것인지는 정하지 않았기 때문에 이 코드를 실행하면 오류가 발생한다.

SELECT * FROM orders
GROUP BY course_title;

👉 그룹의 기준이 되는 필드명과 통계 방법 명시

위에서 발생한 오류를 해결하기 위해 쿼리문을 아래와 같이 수정해주자.

SELECT course_title, COUNT(*) FROM orders
GROUP BY course_title;

쿼리를 실행해보면 알 수 있겠지만, 1주차에서 배운 DISTINCT로 중복제거를 하지 않아도 course_title 필드의 데이터가 중복 제거된 것을 알 수 있다.


👉 오름차순(=값이 작은 순) 또는 내림차순(=값이 큰 순)으로 정렬

ORDER BY를 통해 조회한 데이터를 오름차순(ascending, ASC) 또는 내림차순(descending, DESC)으로 정렬할 수 있다. 오름차순으로 정렬할 때에는 ORDER BY 뒤에 ASC를 생략해도 되지만, 내림차순으로 정렬할 때에는 반드시 ORDER BY 뒤에 DESC를 입력해주어야 한다. 조회한 데이터를 오름차순과 내림차순으로 각각 정렬하면 아래 쿼리문과 같다.

-- 오름차순(ASC 생략 가능)
SELECT course_title, COUNT(*) FROM orders
GROUP BY course_title
ORDER BY COUNT(*) ASC; 

-- 내림차순
SELECT course_title, COUNT(*) FROM orders
GROUP BY course_title
ORDER BY COUNT(*) DESC;

여기까지 3줄 이상의 다소 복잡하게 느껴지는 쿼리문 작성 과정을 살펴보았다. 물론, 한 번에 완벽한 쿼리문을 작성할 수 있으면 더할 나위 없겠지만, 이런 스킬을 습득하기 위해서는 위의 과정과 같이 여러번 수정하여 작성하는 방법에 익숙해져야 한다.

별칭(Alias)

payment_method 필드와 같이 필드명 또는 테이블명이 길거나, COUNT()와 같은 통계 함수를 여러번 사용해야 하는 경우 별칭을 붙여줄 수 있다. 예를 들어, 아래 쿼리문과 같이 payment_method 필드명에는 pay라는 별칭을, COUNT() 결과에는 cnt라는 별칭을, orders 테이블에는 o라는 별칭을 지어줄 수 있다.

SELECT payment_method as pay, COUNT(*) as cnt FROM orders o
GROUP BY pay;

이렇게 지어진 별칭은 앞으로 배울 JOIN, Subquery에서 많이 사용된다.

실습

❓ 주차별 오늘의 다짐 수량 구하기

SELECT week, count(*) FROM checkins
GROUP BY week;

❓ 주차별 오늘의 다짐 좋아요의 최솟값, 최댓값, 평균 구하기

SELECT week, MIN(likes), MAX(likes), AVG(likes) FROM checkins
GROUP BY week; 

❓ 주차별 오늘의 다짐 좋아요의 평균값을 소수점 첫번째 자리까지만 구하기

SELECT week, ROUND(AVG(likes), 1) FROM checkins
GROUP BY week;

❓ 주차별 오늘의 다짐 좋아요의 합계 구하기

SELECT week, SUM(likes) FROM checkins
GROUP BY week;

❓ 웹개발 종합반의 결제수단별 주문건수를 오름차순으로 구하기

SELECT payment_method, COUNT(*) FROM orders
WHERE course_title = '웹개발 종합반'
GROUP BY payment_method
ORDER BY COUNT(*);

❓ 웹개발 종합반의 결제수단별 주문건수를 내림차순으로 구하기

SELECT payment_method, COUNT(*) FROM orders
WHERE course_title = '웹개발 종합반'
GROUP BY payment_method
ORDER BY COUNT(*) DESC;

❓ Gmail을 사용하는 성씨별 회원수 구하기

SELECT name, COUNT(*) FROM users
WHERE email LIKE '%gmail%'
GROUP BY name;

❓ 네이버 이메일로 앱개발 종합반을 신청한 주문의 결제수단별 주문건수 구하기

SELECT payment_method, COUNT(*) FROM orders
WHERE email LIKE '%naver%' AND course_title = '앱개발 종합반'
GROUP BY payment_method;

마치며

2022년 02월 07일(월)부터 오늘까지 3일차 강의를 듣고 있다. 이 교육과정에서는 메타버스 공간인 게더(gather)에서 스온스라는 시스템을 통해 오후반을 담당하시는 김나율 매니저님을 중심으로 여러 사람들이 실시간으로 함께 참여 할 수 있다.

아직까지는 멤버들과 많은 소통을 하진 못했지만, 실시간 영상 대화 및 채팅, 블로그 공유, 슬랙(slack) 메신저를 통해 개발 지식이나 포부 등을 공유함으로써 새로운 자극을 얻게 되고, 또 다른 동기부여도 되는 듯하다.