1. 일반적인 조회 쿼리에서 상황에 맞게 필터링이 필요하다면?
1-1. 개요
기본적인 select ~ from ~ where 형식의 간단한 조회 쿼리에서 해당 조회 결과에 부가적인 요소를 통해 결과를 정렬하거나, 중복을 제거, 또는 일부만 조회하는 형식 등의 특정한 처리가 필요할 때가 있다. 이러한 상황에서 ORDER BY, LIMIT, DISTNCT, GROUP BY, HAVING이 사용된다. 이에 대해 자세히 알아보고자 한다.
1-2. SQL의 일반적인 순서
select
(...)
from
(...)
where
(...)
group by
(...)
order by
(...)
limit
(...)
2. ORDER BY
2-1. 정의
(1) 우선 order by, group by에 대해 정리해 보고자 한다. 두 문법은 일반적인 조회(SELECT) 쿼리를 사용할 때 조회된 데이터들을 정렬(ORDER BY)하고 그룹화(GROUP BY)하는 데 사용되는 주요 문법이다.
(2) order by의 경우 조회된 결과 데이터들을 정렬하는 데 사용된다. 기본값은 오름차순(asc)이며 내림차순(desc) 정렬이 필요한 경우 정렬 기준 컬럼 옆에 desc를 추가한다.
2-2. 기본적인 ORDER BY
select
member_id,
member_name,
created_date,
height
from member
where height >= 164
order by height desc;
(1) where 조건절로 height가 164 이상인 회원들을 프로젝션 컬럼대로 조회한다.
(2) 마지막 order by를 통해 조회 결과를 height 내림차순 기준으로 정렬시킨다.
(3) 위와 같은 형태가 order by의 일반적 형태
2-2. 연속된 ORDER BY
select
member_id,
member_name,
created_date,
height
from member
where height >= 164
order by height desc, created_date asc;
(1) 위의 쿼리와 비교 시, 조회되는 결과에서 아래와 같은 차이점이 있다.
(2) height는 내림차순, created_date는 오름차순 정렬으로 적용하지만 현재 order by가 연속되어 있다.
이런 경우에는 우선 첫 번째 정렬 기준을 적용하고 첫 번째 정렬 기준이 같은 케이스라면, 두 번째 정렬 기준인 created_date에 따라 오름차순으로 정렬된다.
3. LIMIT
3-1. LIMIT
(1) SQL에서 limit 절은 select 조회 쿼리의 결과 로우 개수를 제한하는 역할을 수행한다.
(2) 이를 통해 특정 개수의 로우만을 반환하거나 결과 로우의 일부를 추출할 수 있게 된다.
(3) 일반적으로 limit은 Order by 뒤에 위치하고 정렬된 기준에 따라 반환되는 로우의 개수를 조절할 때 사용된다.
(4) order by가 없더라도 단독으로 limit만 사용 가능하다. 이때는 결과 로우들이 별도의 정렬 기준이 적용되지 않은 채로 개수만 조절되어 조회 결과가 반환된다.
select
member_name,
created_date
from member
order by created_date
limit 10;
3-2. limit n, m
select
member_name,
created_date
from member
order by created_date desc
limit 10, 2;
(1) limit m, n의 경우 (별도의 정렬 기준을 적용하여) 조회된 결과에서 상위 n번째 결과부터 시작하여 m개의 로우를 반환한다.
4. DISTINCT
4-1. DISTINCT
(1) SQL에서 distinct의 경우 데이터를 조회할 때, 중복된 로우을 제거하는 데 사용된다. 이를 통해 결과 집합에 중복된 값을 가지는 로우가 하나만 포함되도록 할 수 있다.
(2) 일반적으로 select distinct 문은 하나 이상의 컬럼을 지정하여 중복을 제거하는 데 사용된다. 결과적으로 각 컬럼의 조합에 대해 중복된 로우가 하나만 포함된다.
select distinct member_address
from member;
(3) distinct는 특정한 컬럼에만 적용시킬 수도 있지만, 결과 전체에 적용이 가능하다.
- 즉, select distinct 뒤에 오는 모든 컬럼을 고려하여 중복된 로우를 제거하게 된다.
select distinct column_1, column_2
from table_name;
(4) distinct는 order by, where, group by와 함께 사용될 수 있으며 결과 집합에서 중복된 값을 제거하는 데 위와 같은 절과 함께 사용 가능하다.
(5) distict는 집계 함수(Aggregation function)과 함께 사용 가능하다.
select count(distinct column_name)
from table_name;
5. Aggregation Function
5-1. Aggregation Function
(1) 데이터베이스에서 집계 함수(Aggregation function)란, 특정 그룹의 데이터를 하나의 값으로 집계 또는 계산 시에 사용된다.
(2) 집계 함수는 주로 group by와 함께 그룹화된 데이터들을 집계 또는 계산 시 사용되며 select의 프로젝션 컬럼들을 대상으로도 계산이 가능하다.
(3) 대표적인 집계 함수들은 아래와 같다.
집계 함수 | 연산 방법 |
count | 선택된 컬럼의 개수를 반환한다. 특정 컬럼이나 행의 개수를 세는 데 사용한다. |
sum | 컬럼의 합계를 계산한다. |
avg | 컬럼의 평균값을 계산한다. |
min | 숫자나 날짜 컬럼에서 최솟값을 찾는다. |
max | min()과 반대로 최댓값을 찾는다. |
select count(column_name1)
from table_name;
select sum(column_name1)
from table_name;
select avg(column_name1)
from table_name;
select max(column_name1)
from table_name;
select min(column_name1)
from table_name;
6. GROUP BY & HAVING
6-1. GROUP BY
(1) group by의 경우 데이터를 말 그대로 그룹화하기 위해 사용된다. 위에서 잠시 언급된 집계 함수와 함께 많이 사용하며 데이터를 필터링할 수 있게 된다.
(2) group by를 통해 특정 컬럼 기준에 따라 그룹으로 나누고, 동일한 값을 가진 로우들이 하나의 그룹으로 묶이게 된다. 이후 집계 함수를 사용해서 각 그룹의 통계 정보를 계산할 수 있다.
select
department,
count(*) as employee_count
from employee
group by department;
(3) 위와 같이 예시 쿼리를 확인해 보자.
- department 컬럼을 기준으로 employee 테이블의 데이터를 그룹화하며, 부서별 직원 수를 계산하여 결과를 반환한다.
select
member_id,
sum(amount) as purhcase_count
from purchases
group by member_id
(4) 예시 : 회원별로 상품 구매 수 조회
select
member_id,
sum(price * amount) as all_purchase_price
from purchases
group by member_id
select
member_id,
avg(amount) as average_amount
from purchases
group by member_id;
(5) 예시 : 회원별로 상품을 구매한 총 금액, 회원별 평균 상품 구매 개수 조회
6-2. HAVING : 그룹화된 결과 집합에서 조건을 주고 싶은 경우
(1) SQL에서 having의 경우 group by 절 뒤에서 사용되며 그룹화된 데이터를 대상으로 조건을 명시할 수 있다.
- where 절과 유사하다고 생각할 수 있는데 where는 개별 컬럼 자체를 필터링하는 데 사용되고, having은 그룹화된 결과를 필터링 할 때 사용한다.
- 아래의 예시로 having 사용 방법을 확인해 보자.
select
member_id,
sum(price * amount) as all_purchase_price
from purchases
group by member_id
having all_purchase_price > 1000;
(2) 예시 : 회원을 그룹화하여 총 구매금액을 계산하지만, 총 구매 금액이 1,000만원 이상인 회원만 조회
select
member_id,
sum(price * amount) as all_purchase_price
from purchases
group by member_id
having all_purchase_price > 1000
order by all_purchase_price asc;
(3) (2)의 조회 결과에서 구매 금액을 기준으로 오름차순 정렬
※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.
개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 댓글로 알려주시면 감사하겠습니다!
댓글