[MySQL] 2.2 데이터 쿼리 - SELECT DISTINCT


http://www.mysqltutorial.org 내용을 따라 익히며 정리한 글입니다. 예시에 나오는 데이터셋은 MySQL 샘플 데이터셋인 classicmodels DB입니다.


1. SELECT DISTINCT 소개

테이블에서 데이터를 뽑아올 때 중복 행이 발생할 수 있다.
SELECT DISTINCT 문을 사용하면 이러한 중복 행들을 제거할 수 있다.

2. SELECT DISTINCT 예시

employees 테이블에서 종업원들이 어떤 성(姓)을 갖고 있는지 살펴본다.

SELECT
lastname
FROM
employees
ORDER BY lastname;

위와 같이 쿼리를 작성하면 아래와 같은 결과가 나온다. Bondur나 Firrelli, Patterson 등 중복된 값들이 있다.

+-----------+
| lastName |
+-----------+
| Bondur |
| Bondur |
| Bott |
| Bow |
| Castillo |
| Firrelli |
| Firrelli |
| Fixter |
| Gerard |
| Hernandez |
| Jennings |
| Jones |
| Kato |
| King |
| Marsh |
| Murphy |
| Nishi |
| Patterson |
| Patterson |
| Patterson |
| Thompson |
| Tseng |
| Vanauf |
+-----------+
23 rows in set (0.00 sec)

이렇게 중복된 값을 보고싶지 않을 때 DISTINCT 절을 사용한다. 결과값이 23개에서 19개로 줄어든 것을 볼 수 있다.

SELECT DISTINCT
lastname
FROM
employees
ORDER BY lastname;
+-----------+
| lastname |
+-----------+
| Bondur |
| Bott |
| Bow |
| Castillo |
| Firrelli |
| Fixter |
| Gerard |
| Hernandez |
| Jennings |
| Jones |
| Kato |
| King |
| Marsh |
| Murphy |
| Nishi |
| Patterson |
| Thompson |
| Tseng |
| Vanauf |
+-----------+
19 rows in set (0.00 sec)

3. SELECT DISTINCTNULL

열에 NULL 값이 있을 때 DISTINCT 절을 사용하면 MySQL은 NULL 값들을 같은 값으로 하나로 표시한다.

customers 테이블의 state 컬럼에서 아래와 같이 쿼리하면 하나의 NULL 값만 나타난다.

SELECT DISTINCT
state
FROM
customers;

+---------------+
| state |
+---------------+
| NULL |
| NV |
| Victoria |
| CA |
| NY |
| PA |
| CT |
| MA |
| Osaka |
| BC |
| Québec |
| Isle of Wight |
| NSW |
| NJ |
| Queensland |
| Co. Cork |
| Pretoria |
| NH |
| Tokyo |
+---------------+
19 rows in set (0.00 sec)

4. 복수 열에서의 SELECT DISTINCT

두 개 이상의 열에서도 DISTINCT 절을 사용할 수 있다. 이 경우 MySQL은 모든 열들의 조합을 사용해 결과값의 유니크함을 결정한다.
가령 customers 테이블에 어떤 도시(city)와 주(state)들이 있는지 보려고 하면 아래와 같이 쿼리를 작성한다.

SELECT DISTINCT
state, city
FROM
customers
WHERE
state IS NOT NULL
ORDER BY state, city
LIMIT 20;
+---------------+---------------+
| state | city |
+---------------+---------------+
| BC | Tsawassen |
| BC | Vancouver |
| CA | Brisbane |
| CA | Burbank |
| CA | Burlingame |
| CA | Glendale |
| CA | Los Angeles |
| CA | Pasadena |
| CA | San Diego |
| CA | San Francisco |
| CA | San Jose |
| CA | San Rafael |
| Co. Cork | Cork |
| CT | Bridgewater |
| CT | Glendale |
| CT | New Haven |
| Isle of Wight | Cowes |
| MA | Boston |
| MA | Brickhaven |
| MA | Cambridge |
+---------------+---------------+
20 rows in set (0.01 sec)

DISTINCT 를 사용하지 않으면 중복값이 나타난다. 아래 예에선 San Francisco가 두 번 나온 걸 볼 수 있다.

SELECT
state, city
FROM
customers
WHERE
state IS NOT NULL
ORDER BY state, city
LIMIT 20;
+---------------+---------------+
| state | city |
+---------------+---------------+
| BC | Tsawassen |
| BC | Vancouver |
| CA | Brisbane |
| CA | Burbank |
| CA | Burlingame |
| CA | Glendale |
| CA | Los Angeles |
| CA | Pasadena |
| CA | San Diego |
| CA | San Francisco |
| CA | San Francisco |
| CA | San Jose |
| CA | San Rafael |
| Co. Cork | Cork |
| CT | Bridgewater |
| CT | Glendale |
| CT | New Haven |
| CT | New Haven |
| Isle of Wight | Cowes |
| MA | Boston |
+---------------+---------------+
20 rows in set (0.00 sec)

5. DISTINCTGROUP BY

집계함수를 사용하지 않은 채로 SELECT 문에서 GROUP BY 절을 사용하면 GROUP BY 절은 DISTINCT 절처럼 작동한다. 어떤 관계가 있는지 아래 세 가지 예시로 살펴본다.

5-1.GROUP BY 사용

SELECT
state
FROM
customers
GROUP BY state
LIMIT 10;
```

+—————+
| state |
+—————+
| NULL |
| BC |
| CA |
| Co. Cork |
| CT |
| Isle of Wight |
| MA |
| NH |
| NJ |
| NSW |
+—————+
10 rows in set (0.00 sec)


#### 5-2. `DISTINCT` 사용

`DISTINCT` 절을 사용해 비슷한 결과를 끌어낼 수 있다.
```sql
SELECT DISTINCT
state
FROM
customers
LIMIT 10;
```

+———-+
| state |
+———-+
| NULL |
| NV |
| Victoria |
| CA |
| NY |
| PA |
| CT |
| MA |
| Osaka |
| BC |
+———-+
10 rows in set (0.00 sec)


#### 5-3. `DISTINCT` + `ORDER BY` 사용

`DISTINCT` 를 사용한 5-2 예시에 `ORDER BY` 를 추가하면 5-1과 똑같은 결과가 나온다.

```sql
SELECT DISTINCT
state
FROM
customers
ORDER BY state
LIMIT 10;

+---------------+
| state |
+---------------+
| NULL |
| BC |
| CA |
| Co. Cork |
| CT |
| Isle of Wight |
| MA |
| NH |
| NJ |
| NSW |
+---------------+
10 rows in set (0.00 sec)

위 예시에서 보듯 DISTINCTGROUP BY 의 특수한 경우라고 할 수 있다.
DISTINCT 는 결과셋를 따로 정렬하지 않지만GROUP BY 는 결과셋을 정렬해서 리턴한다는 차이가 있다.

6. DISTINCT 와 집계 함수

DISTINCT 는 결과값에 SUM, AVG, COUNT 같은 집계 함수를 적용하기 전에 중복값을 제거하는데 사용되기도 한다.

SELECT
COUNT(DISTINCT state)
FROM
customers
WHERE
country = 'USA';
+-----------------------+
| count(distinct state) |
+-----------------------+
| 8 |
+-----------------------+
1 row in set (0.00 sec)

7. DISTINCTLIMIT

DISTINCTLIMIT 와 함께 쓰면 LIMIT 로 제한한 수만큼 특정 행 값을 찾았을 때 탐색을 바로 중단한다.

SELECT DISTINCT
state
FROM
customers
WHERE
state IS NOT NULL
LIMIT 5;

+----------+
| state |
+----------+
| NV |
| Victoria |
| CA |
| NY |
| PA |
+----------+
5 rows in set (0.01 sec)
© 2019 THE DATASCIENTIST All Rights Reserved.
Theme by hiero