DEV Community

orca orcinus
orca orcinus

Posted on

SQL 을 조금 더 알아보자

<목차>

  1. SELECT 와 별칭의 범위
  2. GROUP BY 작동 원리
  3. GROUP BY 와 SELECT
  4. HAVING 이 존재하는 이유
  5. JOIN 의 실제 작동 원리

## 1. SELECT 와 별칭의 범위
지난 글에서 SQL의 실제 작동 순서를 알아보았다

실제로는 SELECT의 작동 위치가
FROM 위가 아닌 HAVING 아래라는 것이 핵심인데
이것을 모를 때 생기는 가장 큰 오해가 있다.
'SELECT 에서 만든 별칭은 그보다 윗쪽에 있는 절에서는 사용할 수 없다'는 것이다.
예를 들면 SELECT에서 만든 AS '별칭'은
그 아래에 있는 ORDER BY에서는 당연히 사용할 수 있지만
윗쪽에 있는 WHERE 절에서는 원칙적으로 사용할 수 없다.
그런데 종종 어떤 곳에서는 WHERE 절에서 사용이 되기도 한다.
그건 저 실수를 저지르는 사람들이 너무 많다보니
최신DB들이 편의성을 위해 인식하도록 바꿔놓은 것이다.
원래는 불가능한 것이 맞다.

2. GROUP BY 작동 원리

예를 들어, 이런 테이블에서

SELECT InvoiceNo, COUNT(*) AS cnt
FROM data3
GROUP BY InvoiceNo
Enter fullscreen mode Exit fullscreen mode

GROUP BY와 COUNT(*)을 이용하면

이런 결과가 나온다.
그런데 궁금하다.
우리 눈에는 하나의 컬럼 값인데 도대체 어떻게 몇 개인지 출력된 걸까?
GROUP BY는 하나의 컬럼 값만 남기고 삭제하는 것이 아니라
해당 컬럼 값의 이름으로 '집계용 객체'를 만드는 것이다.
데이터 베이스 용어로는 "결과 셋(Result Set)을 재구성했다"라고 한다.
그래서 눈에 보이는 컬럼 값은 하나인데도 여러가지 연산이 가능한 것이다.
예를 들어, 아래테이블을 그룹화하면

name   age
-----  ----
Alice  20
Alice  21
Alice  23
Enter fullscreen mode Exit fullscreen mode

내부적으로는 이런 구조가 되는 것이다

그룹(name='Alice') → [20,21,23]
Enter fullscreen mode Exit fullscreen mode

3. GROUP BY 와 SELECT

GROUP BY를 처음 사용하면 이런 실수를 자주 한다.
GROUP BY에서 지정한 컬럼이 SELECT에 없는 오류
GROUP BY에서 지정하지 않은 컬럼이 SELECT에 있는 오류

이런 실수를 반복하다보면 그룹화한 컬럼이 반드시 출력되어야하는구나를 알게되는데
여기서 또 궁금하다.
왜 그렇지?
그리고 SELECT에서 다른 함수들은 왜 출력될 수 있는 거지?
간단히 말하면, '그룹화한 객체 옆에는 그것을 대표할 수 있는 값만 올 수 있기 때문'이다
데이터 베이스의 기본 구조를 떠올려보면
'하나의 행 = 어떤 하나의 사물/사건의 정보를 담은 단위'이다
즉, 행 하나하나가 어떤 사물/사건인 것이다.
그런데 어떤 컬럼이 그룹화 됐을 때,
원래 하던 대로 그 옆에 '하나의 행'에 대한 정보를 넣어버리면?
데이터 베이스의 기본 구조가 완전히 망가진다
테이블 = 어떤 종류의 객체
행 = 그 객체의 개별 인스턴스
컬럼 = 그 인스턴스를 설명하는 속성
이기 때문이다.
이러한 이유로 그룹화 컬럼 옆에는 반드시 그것을 대표하는 값이 와야하는 것이다.

4. HAVING 이 존재하는 이유

나는 처음 공부할 때, WHERE이 있는데 왜 HAVING이 또 있는지 궁금했다.
왜 굳이 조건 필터링 예약어가 2개일까?
글을 열심히 읽은 독자라면 이제 HAVING이 존재하는 이유를 자연히 알 것이다.
WHERE은 행 단위로 필터링하는 기능을 수행하고
HAVING은 그룹을 필터링하는 기능을 수행한다.
즉, '하나의 행'들로 이루어진 테이블을 필터링하는 것과
'그룹'들로 이루어진 테이블을 필터링하는 것의 차이다.

5. JOIN 의 실제 작동 원리

A) 논리적 관점 - 개념
테이블A와 테이블B를 크로스 조인(Cartesian Product)한다.
곱집합을 만드는 것으로 가능한 모든 조합이 생성 된다

예를 들어, 테이블A가 20행이고 테이블B가 30행이면 600행의 테이블이 만들어진다.
여기서 JOIN의 종류와 조건(ON condition)에 맞는 행만 남기는 것이다.
INNER JOIN - 조건에 맞는 행만 남긴다.
LEFT JOIN - 왼쪽 테이블의 행 + 조건에 맞는 행만 남긴다.
이래서 LEFT JOIN을 쓰면 NULL이 들어간 행이 많이 보이는 것이다.
B) 물리적 관점 - 실제 작동
하지만 매번 저렇게 곱집합을 생성해버리면 불필요한 연산량이 폭발하기 떄문에
실제로는 곱집합을 전부 만들지 않도록 똑똑한 알고리즘을 사용하고 있다.
ex. Nested Loop Join, Hash Join 등

Top comments (0)