본문 바로가기
DEV/DB & SQL

[SQL] Group By, Having, Order By

by 무사뎀벨레 2024. 11. 28.

 

 

 

 

 

 

GROUP BY


GROUP BY데이터를 특정 컬럼 기준으로 그룹화시키는 명령어이다.

예를 들어, 연령별 평균 매출액을 조회하는 쿼리를 작성할 때 연령별로 그룹화하여 결과를 정렬할 수 있다.

 

다중으로 그룹 나누기

- 그룹을 나누고, 다시 그 그룹 안에서 세부그룹으로 나눌 수 있음

- GROUP BY COL1, COL2이라고 쿼리를 작성하면 COL1안에서 다시 COL2로 나누기 가능

- 위의 방법을 예시로 들자면, 연령별 성별 평균 매출액을 추출하는 쿼리에서 연령별로 먼저 그룹을 나누고, 그다음 연령별로 먼저 그룹이 나눠진 그룹에서 또 성별로 그룹을 나눌 수 있음

 

집계함수의 필요

- 각 그룹에 대한 연산 결과(합, 평균, 개수 등)를 산출하기 위해서는 집계함수가 필요

- GROUP BY 절에 있는 컬럼은 반드시 SELECT 절에도 존재해야 함

- GROUP BY 절에도 SUBSTR, INSTR 등등의 다양한 함수 사용 가능

 

그룹 함수

- GROUP BY 절에도 아래의 표와 같이 SUBSTR, INSTR 등등의 다양한 함수 사용 가능

- 하나 이상의 행을 그룹으로 묶어 연산하기 위한 함수

- GROUP BY 기준으로 나눠진 각 그룹을 연산하는 역할

- COUNT 함수를 제외한 나머지 그룹함수는 NULL 값 제외하고 계산(COUNT는 NULL을 포함)

함수종류 정의 참고
COUNT '행'의 개수 데이터 NULL인 경우도 COUNT
SUM 합계 NULL 값 제외하고 연산
AVG 평균 NULL 값 제외하고 연산
그러나, NULL값 포함해 평균 계산하고 싶다면 NULL을 0으로 채워줘야 함
MAX 최대값 NULL 값 제외하고 연산
MIN 최소값 NULL 값 제외하고 연산
STDDEV 표준편차 NULL 값 제외하고 연산
VARIANCE 분산 NULL 값 제외하고 연산

 

 

--  ########## 1. COUNT ##########
SELECT 
	player_num
	, COUNT(*)
FROM PLAYER_TB
GROUP BY player_num;
 
SELECT 
	player_num
	, COUNT(player_goal)
FROM PLAYER_TB
GROUP BY player_num; 
 
-- GROUP BY를 사용하지 않아도 집계함수 자체는 사용 가능(테이블 모든 행을 하나의 그룹으로 판단)
SELECT 
	COUNT(*)
FROM PLAYER_TB; 
  
  
  
  
-- ########## 2. MAX, MIN ##########
-- 선수 명단 테이블 내 최대연봉, 최소연봉
SELECT 
	MAX(player_salary) AS maxSal
	, MIN(player_salary) AS minSal
FROM PLAYER_TB;
  
-- 선수 명단 테이블 내 포지션별 최대연봉, 최소연봉
SELECT 
	player_position
	MAX(player_salary) AS maxSal
	, MIN(player_salary) AS minSal
FROM PLAYER_TB
GROUP BY player_position;
 
-- 선수 명단 테이블 내 선수 등번호별 가장 큰 키, 작은 키(모든 값이 NULL이면, NULL 출력)
SELECT 
	player_num
	, MAX(player_height)
	, MIN(player_height)
FROM PLAYER_TB
GROUP BY player_num;
 
 
 
 
-- ########## 3. AVG ##########
-- 선수 명단 테이블 내 각 팀별 키의 평균값을 구해 소수점 1번째 자리까지 출력
SELECT 
	team_id
	, ROUND(AVG(player_height), 1) AS avgHeight
FROM PLAYER_TB
GROUP BY team_id;
 
 
 
-- ########## 4. SUM ##########
-- 선수 명단 테이블 내 전체 선수의 연봉 합계
SELECT 
	SUM(player_salary) AS teamSumSalary
FROM PLAYER_TB;
  
-- 선수 명단 테이블 내 각 팀별 선수의 연봉 합계
SELECT 
	team_id
	, SUM(player_salary) AS 연봉합계
FROM PLAYER_TB
GROUP BY team_id;

 

 

 

 

 

 

 

HAVING


HAVING절GROUP BY로 그룹화가 완료된 후에 대상을 필터링하는 문법이다. 그룹화된 결과에 조건을 걸어주는 역할을 하며, HAVING절에는 SELECT 구문에서 사용하는 AS 별칭 사용이 불가하다.

 

[SQL] WHERE 절에서는 별칭(alias)을 사용할 수 없음 / 대안 방법

WHERE절에서 alias(열 별칭)을 사용하지 못하는 경우SELECT에서 쓴 alias(열 별칭) 를 WHERE절에 쓰지 못하는 이유는 다음과 같다. 대부분의 SQL 데이터베이스에서 SELECT 절은 FROM 절 뒤와 WHERE 절 앞에서 처

hajoung56.tistory.com

 

 

집계 함수에 조건을 줄 수 있는데, HAVING절을 사용할 때 WHERE절과 헷갈리지 않게 조심해야 한다.

처음부터 테이블 자체에 조건을 걸고 싶다면 WHERE 절을 사용하고, 그룹별로 묶인 컬럼에 조건을 걸고 싶다면 HAVING 절을 사용하면 된다.

 

WHERE는 GROUP BY보다 먼저 실행되고, HAVING GROUP BY보다 나중에 실행된다. WHERE → GROUP BY → HAVING순서이므로 HAVING은 GROUP BY의 영향을 받는다. 따라서 GROUP BY에 입력된 컬럼에 의해서 입력 가능한 컬럼의 제약을 받게 된다.

 

쿼리의 실행 순서

① PLAYER_TB(선수 명 테이블) 접근
② team_id가 ‘T001’ , ‘T002’ , ‘T003’인 튜플만 대상으로 필터링
③ team_id컬럼을 기준으로 그룹화
④ 그룹화가 완료된 튜플에서 SUM(player_salary) 이 10000 이상인 대상을 필터링
⑤ team_id컬럼과 SUM( player_salary ) 집계값을 출력

-- 5
SELECT player_num, sum(player_salary)

-- 1
FROM PLAYER_TB

-- 2
WHERE team_id IN ('T001', 'T002', 'T003')

-- 3
GROUP BY team_id

-- 4
HAVING SUM(player_salary) >= 10000;

 

 

 

 

 

ORDER BY


ORDER BY절특정 컬럼을 기준으로 데이터 집합을 오름차순 혹은 내림차순 정렬하기 위한 명령어이다.

SELECT로 데이터가 추출된 이후에 실행되며, SELECT에 입력되지 않은 컬럼도 사용 가능하다. GROUP BY가 명시된 경우에는 GROUPY BY에 의해 한정된 컬럼만 사용 가능하며, 컬럼 이름 이외에도 ALIAS, 숫자 등으로도 표시 가능하다.

 

아래 예시와 같이 ORDER BY COL1, COL2... 와 같이 여러 개의 컬럼을 기준으로 정렬할 수 있다.

SELECT 
	*
FROM PLAYER_TB
ORDER BY 
	team_id
	, player_salary DESC ;

 

아래 코드와 같이, SELECT절의 컬럼 순서 혹은 별칭으로도 정렬이 가능하다.

SELECT
	player_name AS p_nm
	, player_number AS p_num
FROM PLAYER_TB
-- 위 player_name의 별칭을 p_nm으로 설정 후 OERDR BY절에서 p_nm으로 사용
OERDR BY p_nm

 

 

또한, 아래 예시 쿼리와 같이 ORDER BY를 사용할 때에 기본 정렬값은 ASC(오름차순)로 설정되어 있으므로 오름차순 정렬 시에는 입력 필요가 없고 내림차순의 경우 DESC를 입력하여 사용한다.

-- 오름차순(ASC) 사용시
SELECT
	*
FROM TB_PLAYER
ORDER BY player_num

-- 내림차순(DESC) 사용시
SELECT
	*
FROM TB_PLAYER
ORDER BY player_num DESC

 

 

반응형

댓글