SELECT 문을 응용해보자

검색결과 정렬

정렬
SELECT ~ ORDER BY 열1 [ , 열2, ... ]

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

  • 오름차순 ASC (디폴)

  • 내림차순 DESC

테이블을 요약하는 함수

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

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

  • 복수 행에 대해 집계를 수행하는 함수

  • 단일 행의 값에 대해 조작이나 계산을 수행하는 함수

전자의 경우 '집약함수(집계함수)' 라 부른다.

  • COUNT 테이블의 행수를 알려주는 함수

  • SUM 테이블의 수치 데이터를 합계하는 함수

  • AVG 테이블의 수치 데이터 평균을 구하는 함수

  • MAX 테이블의 임의열 데이터 중 최대값을 구하는 함수

  • MIN 테이블의 임의열 데이터 중 최소값을 구하는 함수

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

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' 함수는 콤마로 구분되는 문자열의 결합을 돌려준다. 만약 애플리케이션 측에서 사용시에는 함수 결과가 매우 길 수 있어 주의해야 한다.

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 는 선택한 행의 중복을 배제하고 싶은 경우에 이용하는데, 집약함수에도 이용할 수 있다.

district(행정구역) 이 중복 결합
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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)
DISTINCT 키워드로 중복을 회피한 경우
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)

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

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

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

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

GROUP BY 없을 경우
mysql> select count(*) from city where countrycode = 'KOR';
+----------+
| count(*) |
+----------+
|       70 |
+----------+
1 row in set (0.00 sec)
GROUP BY 있는 경우
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)

나눈 그룹에 조건 추가

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

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

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

집약한 결과에 조건 지정

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

SELECT ~ FROM ~ GROUP BY ~ HAVING 그룹의 값에 대한 조건 
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 에도 집약함수를 기술 할 수 있다.

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 문의 작성 순서는 다음과 같다.

SELECT ~ FROM ~ GROUP BY ~ HAVING ~ ORDER BY ~

Last updated