본문 바로가기
데이터 모델과 SQL

[SQL 이해하기] - 8.3. SQL: SELECT III - WHERE, GROUP BY

by 영바이트 2023. 7. 3.

 

SELECT 구문은 기본적으로 FROM 절의 대상에서 모든 행(ROW)의 데이터를 출력한다. 하지만 보통 이와 같은 경우는 거의 없다. 조건을 지정하고 해당 조건을 만족하는 행의 데이터를 가져오도록 도와주는 WHERE 절에 대해 살펴보자.

 

WHERE 절의 기본적인 문법은 아래와 같다.

SELECT 컬럼 1, 컬럼 2, ... FROM 테이블 WHERE 조건

 

조건은 보통 '컬럼' = '값' 형태로 주어진다. 예를 들어 주소 도시가 'London'인 회원 정보를 출력하는 SQL은 아래와 같다.

SELECT FIRST_NAME, LAST_NAME, CITY FROM MEMBER WHERE CITY='London';

 

만약 조건이 2개 이상이라면 AND 또는 OR를 이용해서 조건들을 연결시킬 수 있다.

SELECT FIRST_NAME, LAST_NAME, CITY FROM MEMBER WHERE CITY='London' AND FIRST_NAME='Mark';

 

조건에 일반적으로 '같다'를 의미하는 동등연산자인 '='를 사용하지만 아래와 같이 '같지 않다'를 의미하는 부정 비교 연산자들을 반드시 기억할 필요가 있다.

!= 같지 않음 WHERE COL != 10
^= 같지 않음 WHERE COL ^= 10
<> 같지 않음 WHERE COL <> 10
NOT 컬럼이름= 같지 않음 WHERE NOT COL = 10

 

그리고 아래와 같은 비교 연산자들도 자주 사용된다.

BETWEEN A AND B A, B를 포함한 A와 B 사이 WHERE COL BETWEEN 1 AND 10
LIKE '비교 문자열' 비교 문자열을 포함하는 WHERE COL LIKE '%고등학교'
IN (LIST) LIST 중 하나와 일치 WHERE COL IN (1, 3, 5)
IS NULL NULL 값인지 여부 WHERE COL IS NULL

LIKE 조건에서 %는 0글자 이상의 문자와 매칭(matching)된다. 따라서 LIKE %고등학교% 조건을 적용하면 대상 컬럼의 값에 '고등학교'가 포함된 모든 문자열들이 검색된다.

 

부정 조건을 일반 조건으로 변환하는 드 모르간의 법칙(De Morgan's law)도 기억해 놓을 가치가 있다.

 

- 드 모르간의 법칙

NOT (A or B) → NOT A NOT(or) NOT B → NOT A and NOT B

 

예) NOT (SAL < 300 AND SAL > 500) → SAL >= 300 OR SAL <= 500 = SAL BETWEEN 300 AND 500

 

아래는 WHERE 조건절을 사용할 때 기억해두고 있으면 SQL을 작성할 때 좋은 내용들이다.

 

· WHERE 절은 SELECT절 보다 먼저 수행된다. 따라서 SELECT 절에서 사용된 Alias를 사용할 수 없다.

· 논리 연산자의 우선순위는 () → NOT → AND → OR 순서이다.

· NULL과의 연산(+, -, *, /) 결과는 항상 NULL이다.

· 조건식에서 컬럼 이름은 좌측, 우측 모두에 위치할 수 있다.

 


 

SELECT 대상 데이터를 그룹으로 묶고 해당 그룹 별로 데이터를 정리한 후 출력하는 상황도 자주 발생한다. 이 때 SELECT 구문과 함께 GROUP BY와 HAVING 절이 자주 사용된다. 예를 들어 특정 컬럼의 값을 기준으로 그룹핑하고 특정 조건을 만족하는 그룹만 출력하고자 할 때는 아래와 같이 SQL을 구성한다.

SELECT 컬럼 1, 컬럼 2, ... FROM 대상 테이블 WHERE 조건 GROUP BY 그룹핑 기준 컬럼 HAVING 조건;

 

위 SQL을 실행하면 대상 테이블에서 WHERE 조건에 해당하는 행(ROW)들을 선택한 후 GROUP BY 조건으로 선택된 행들을 묶고(그룹핑하고) 이렇게 그룹핑된 집합 중 HAVING에 명시한 조건을 만족하는 행들만 출력된다. 그 과정이 다소 복잡해보이기 때문에 SQL의 실행 순서로 동작을 정리하고 기억하는 것이 좋다.

 

FROM → WHERE → GROUP BY → HAVING → SELECT (→ ORDER BY)

 

예를 들면 아래와 같다.

SELECT PRODUCT_CODE, COUNT(ORDER_CNT) AS TOTAL_ORDERS
FROM ORDER_PRODUCT
WHERE ORDER_DATE BETWEEN '20210701' AND '20210731'
GROUP BY PRODUCT_CODE
HAVING COUNT(ORDER_CNT) >= 1000;

 

위 SQL을 살펴보면 ORDER_PRODUCT 테이블에서 WHERE 조건절을 이용해서 주문 날짜(ORDER_DATE)가 2021년 7월인 행(ROW)들을 선택한 후 GROUP BY 절을 이용해서 이들 행을 PRODUCT_CODE 컬럼을 기준으로 묶는다. 그리고 이렇게 묶인 행들 중 ORDER_CNT 컬럼의 값의 갯수가 1,000개 이상인 그룹을 선택한다.

 

GROUP BY 절을 사용하면 GROUP BY 조건을 만족하는 행들이 하나의 행으로 요약된다. 따라서 GROUP BY 절에 지정한 컬럼과 집계 함수(COUNT, SUM, AVG 등)의 결과만 출력할 수 있다. 예를 통해 살펴보자.

 

SELECT STUDSTATE, COUNT(STUDENTID) FROM STUDENTS GROUP BY STUDSTATE;

STUD COUNT(STUDENTID)
---- ----------------
TX                  3
WA                  9
CA                  2
OR                  4

 

하지만 아래와 같이 GROUP BY 절에 지정하지 않은 컬럼을 출력하려고 하면 오류가 발생한다.

SELECT STUDSTATE, STUDCITY FROM STUDENTS GROUP BY STUDSTATE;

SELECT STUDSTATE, STUDCITY FROM STUDENTS GROUP BY STUDSTATE
                  *
1행에 오류:
ORA-00979: GROUP BY 표현식이 아닙니다.

 

HAVING 절은 GROUP BY절 뒤에 위치하면서 집계된 데이터에 대한 조건을 부여하지만 테이블 전체가 하나의 그룹인 경우 GROUP BY 절 없이 HAVING 조건절만 단독으로 사용될 수 있다.

 

HAVING 절은 SELECT 절 이전에 실행된다. 따라서 SELECT 절에서 출력 결과 컬럼들에 부여한 별명(Alias)을 HAVING 절에서 사용할 수 없다는 것도 기억할 필요가 있다.

 

 


ORDER BY 절은 ORDER BY 절에 지정한 컬럼을 기준으로 출력 값을 오름차순(ASC, ascending), 내림차순(DESC, descending)으로 정렬해준다. 예를 들면 아래와 같다. 기본은 오름차순(ASC)이고 내림차순 정렬을 원하면 내림차순(DESC) 키워드를 명시해주어야 한다.

 

SELECT STUDSTATE, COUNT(STUDENTID) AS NUM FROM STUDENTS GROUP BY STUDSTATE ORDER BY NUM DESC;

STUD        NUM
---- ----------
WA            9
OR            4
TX            3
CA            2

 

이어질 포스팅에서는 둘 이상의 테이블에서 데이터를 꺼낼수 있도록 해 주는 JOIN 연산에 대해 살펴보도록 하자.

 

댓글