# SELECT 문을 응용해보자

## 검색결과 정렬

{% code title="정렬" %}

```sql
SELECT ~ ORDER BY 열1 [ , 열2, ... ]
```

{% endcode %}

ORDER BY 에 사용한 열명을 '정렬키' 라고 한다.&#x20;

* 오름차순 ASC (디폴)
* 내림차순 DESC

## 테이블을 요약하는 함수

SQL 에서 데이터에 대해 어떠한 조작이나 계산을 수행하려면 '함수' 라는 도구를 사용한다.

함수는 크게 2 종류로 나뉜다.

* 복수 행에 대해 집계를 수행하는 함수
* 단일 행의 값에 대해 조작이나 계산을 수행하는 함수

전자의 경우 **'집약함수(집계함수)'** 라 부른다.&#x20;

* **COUNT** 테이블의 행수를 알려주는 함수
* **SUM** 테이블의 수치 데이터를 합계하는 함수
* **AVG** 테이블의 수치 데이터 평균을 구하는 함수
* **MAX** 테이블의 임의열 데이터 중 최대값을 구하는 함수
* **MIN** 테이블의 임의열 데이터 중 최소값을 구하는 함수&#x20;

이러한 **집약함수는 기본적으로 NULL을 제외**하고 집계하는데, COUNT 함수만은 'COUNT(\*)' 로 표기하여 NULL을 포함한 전체 행을 집계한다. 또한, SUM, AVG 이외의 집약함수는 수치 데이터 외에도 이용 가능하다. 예를 들어, 도시명 최대값은 'Y' 로 시작하는 'Yosu', 최소값은 'A' 로 시작하는 'Andong' 이 된다.

```sql
mysql> select name from city where countrycode = 'KOR';
+------------+
| name       |
+------------+
| Seoul      |
| Pusan      |
| Inchon     |

~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~

| Yongchon   |
| Sachon     |
| Uiwang     |
| Naju       |
| Namwon     |
| Tonghae    |
| Mun-gyong  |
+------------+
70 rows in set (0.00 sec)

mysql> select max(name) from city where countrycode = 'KOR';
+-----------+
| max(name) |
+-----------+
| Yosu      |
+-----------+
1 row in set (0.00 sec)

mysql> select min(name) from city where countrycode = 'KOR';
+-----------+
| min(name) |
+-----------+
| Andong    |
+-----------+
1 row in set (0.00 sec)
```

## 문자열을 집약하는 GROUP\_CONCAT

문자열에 대한 집약함수는 SQL 표준에는 없으나 MySQL에는 'GROUP\_CONCAT' 함수가 있다. 'GROUP\_CONCAT' 함수는 콤마로 구분되는 문자열의 결합을 돌려준다. 만약 애플리케이션 측에서 사용시에는 함수 결과가 매우 길 수 있어 주의해야 한다.

```sql
mysql> select group_concat(name) from city where countrycode = 'KOR' and district = 'Chollabuk';
+-------------------------------------------+
| group_concat(name)                        |
+-------------------------------------------+
| Chonju,Iksan,Kunsan,Chong-up,Kimje,Namwon |
+-------------------------------------------+
1 row in set (0.00 sec)
```

## DISTINCT로 중복 회피

DISTINCT 는 선택한 행의 중복을 배제하고 싶은 경우에 이용하는데,  집약함수에도 이용할 수 있다.

{% code title="district(행정구역) 이 중복 결합" %}

```sql
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| group_concat(district)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Seoul,Pusan,Inchon,Taegu,Taejon,Kwangju,Kyongsangnam,Kyonggi,Kyonggi,Kyonggi,Kyonggi,Chollabuk,Chungchongbuk,Kyonggi,Kyonggi,Kyongsangbuk,Kyongsangnam,Kyongsangnam,Kyonggi,Chungchongnam,Kyongsangnam,Chollabuk,Kyonggi,Kyongsangbuk,Kyonggi,Kyongsangbuk,Chollabuk,Cheju,Kyongsangnam,Chollanam,Chollanam,Kyonggi,Kang-won,Kyonggi,Kang-won,Kyonggi,Kang-won,Chungchongbuk,Kyongsangbuk,Chollanam,Kyongsangbuk,Kyonggi,Kyongsangnam,Kyonggi,Chungchongnam,Kyongsangnam,Kyongsangbuk,Chungchongnam,Kyonggi,Chollabuk,Chungchongbuk,Chungchongnam,Kyonggi,Kyongsangnam,Chungchongnam,Kyongsangbuk,Kyongsangnam,Kyongsangbuk,Chungchongnam,Chollanam,Kyongsangnam,Kyonggi,Chollabuk,Kyongsangbuk,Kyongsangnam,Kyonggi,Chollanam,Chollabuk,Kang-won,Kyongsangbuk |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

{% endcode %}

{% code title="DISTINCT 키워드로 중복을 회피한 경우" %}

```sql
mysql> select group_concat(distinct district) from city where countrycode = 'KOR';
+------------------------------------------------------------------------------------------------------------------------------------------+
| group_concat(distinct district)                                                                                                          |
+------------------------------------------------------------------------------------------------------------------------------------------+
| Cheju,Chollabuk,Chollanam,Chungchongbuk,Chungchongnam,Inchon,Kang-won,Kwangju,Kyonggi,Kyongsangbuk,Kyongsangnam,Pusan,Seoul,Taegu,Taejon |
+------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

{% endcode %}

## 데이터를 그룹으로 나누는 GROUP BY

대상이 되는 데이터를 몇 개의 그룹으로 나눠서 집약하는 것도 가능하다. 예를 들어, '행정구역(district) 마다', '국가(country) 마다' 집약하는 식이다.

```sql
SELECT ~ FROM 테이블명 GROUP BY 열명1 [ , 열명2, ... ]
```

GROUP BY 로 지정한 열을 '집약 키' 또는 '그룹화 키' 로 부르며, 복수 열을 콤마로 구분해 지정할 수 도 있다.

{% code title="GROUP BY 없을 경우" %}

```sql
mysql> select count(*) from city where countrycode = 'KOR';
+----------+
| count(*) |
+----------+
|       70 |
+----------+
1 row in set (0.00 sec)
```

{% endcode %}

{% code title="GROUP BY 있는 경우" %}

```sql
mysql> select district, count(*) from city where countrycode = 'KOR' group by district;
+---------------+----------+
| district      | count(*) |
+---------------+----------+
| Seoul         |        1 |
| Pusan         |        1 |
| Inchon        |        1 |
| Taegu         |        1 |
| Taejon        |        1 |
| Kwangju       |        1 |
| Kyongsangnam  |       11 |
| Kyonggi       |       18 |
| Chollabuk     |        6 |
| Chungchongbuk |        3 |
| Kyongsangbuk  |       10 |
| Chungchongnam |        6 |
| Cheju         |        1 |
| Chollanam     |        5 |
| Kang-won      |        4 |
+---------------+----------+
15 rows in set (0.00 sec)
```

{% endcode %}

## 나눈 그룹에 조건 추가

그룹으로 나눠서 집약한 값에 대해 조건을 설정하려면 어떻게 해야 할까?

'조건'이 있다면 WHERE 구문에 조건을 추가하고 싶지만 오류가 발생한다. COUNT 같은 **집약함수를 작성할 수 있는 경우는 SELECT와 ORDER BY, HAVING 뿐이다.**

```sql
mysql> select district, count(*) from city where countrycode = 'KOR' and count(*) = 4 group by district;
ERROR 1111 (HY000): Invalid use of group function
```

## 집약한 결과에 조건 지정

그룹마다 집약한 값을 조건으로 선택하고 싶다면 HAVING 뒤에 조건을 지정해야 한다.

```sql
SELECT ~ FROM ~ GROUP BY ~ HAVING 그룹의 값에 대한 조건 
```

```sql
mysql> select district, count(*) from city where countrycode = 'KOR' group by district having count(*) = 6;
+---------------+----------+
| district      | count(*) |
+---------------+----------+
| Chollabuk     |        6 |
| Chungchongnam |        6 |
+---------------+----------+
2 rows in set (0.00 sec)
```

또한, 앞에서 말한대로 SELECT와 ORDER BY 에도 집약함수를 기술 할 수 있다.&#x20;

```sql
mysql> select district, count(*) from city where countrycode = 'KOR' group by district having count(*) > 6 order by count(*) desc;
+--------------+----------+
| district     | count(*) |
+--------------+----------+
| Kyonggi      |       18 |
| Kyongsangnam |       11 |
| Kyongsangbuk |       10 |
+--------------+----------+
3 rows in set (0.00 sec)
```

SELECT 문의 작성 순서는 다음과 같다.

```sql
SELECT ~ FROM ~ GROUP BY ~ HAVING ~ ORDER BY ~
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://koseungbin.gitbook.io/wiki/books/undefined-1/sql/select-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
