고인물을 지양하는 블로그

MySQL: SELECT_2 본문

카테고리 없음

MySQL: SELECT_2

yunjaeGong 2019. 8. 30. 01:29

데이터를 그룹으로 나누기

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

지정한 그룹 열마다 집약해서 그룹 열로 나눈 그룹 수의 결과를 되돌려준다

select district, count(*) from city where countrycode="KOR" GROUP BY district;
+---------------+----------+
| district      | count(*) |
+---------------+----------+
| Cheju         |        1 |
| Chollabuk     |        6 |
| Chollanam     |        5 |
| Chungchongbuk |        3 |
| Chungchongnam |        6 |
			...
| Kyonggi       |       18 |
| Kyongsangbuk  |       10 |
| Kyongsangnam  |       11 |
| Pusan         |        1 |
| Seoul         |        1 |
| Taegu         |        1 |
| Taejon        |        1 |
+---------------+----------+

중복 제거

선택한 행의 값이 중복되어 이를 없애고 싶을 경우 DISTINCT를 사용한다.

select group_concat(district) from city where countrycode="KOR";
| 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, .... |

위와 같이 행정구역을 단순하게 GROUP_CONCAT한다면 중복 행정구역명이 여러 번 나타난다. 하지만, 아래와 같이 DISCTINCT를 사용하면

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 |
+------------------------------------------------------------------------------------------------------------------------------------------+

행정구역명이 중복 없이 출력된다.

 

나눈 그룹에 조건 추가

그룹으로 나눠서 집약한 값(count(*))에 대해 조건을 설정하고 싶은 경우

e.g. 센 값이 '각 행정구역에 속한 도시의 수'일 때, 속한 도시의 수가 6개인 행정구역을 선택하고 싶을 때.

WHERE 구문을 사용하면 되지만, 다음 문장은 에러가 발생한다.

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

 

집약한 결과에 조건 지정

select district, count(*) from city where countrycode="KOR" group by district having count(*) = 6;
+---------------+----------+
| district      | count(*) |
+---------------+----------+
| Chollabuk     |        6 |
| Chungchongnam |        6 |
+---------------+----------+

 

검색 결과 정렬

SELECT ~ ORDER BY 열1[, 열2, ...];

해당 그룹 내 행정구역 수로 정렬 (오름차순: ASC(default), 내림차순: DESC)

select district, count(name), group_concat(name) from city where countrycode="KOR" group by district order by count(name) desc;
+---------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------+
| district      | count(name) | group_concat(name)                                                                                                                  |
+---------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------+
| Kyonggi       |          18 | Kuri,Ichon,Kwangmyong,Pyongtaek,Paju,Yong-in,Ansan,Koyang,Anyang,Shihung,Hanam,Kunpo,Uijongbu,Puchon,Suwon,Uiwang,Namyangju,Songnam |
| Kyongsangnam  |          11 | Koje,Chinhae,Kimhae,Miryang,Chang-won,Masan,Chinju,Sachon,Yangsan,Ulsan,Tong-yong                                                   |
| Kyongsangbuk  |          10 | Yongju,Sangju,Kimchon,Pohang,Kumi,Yongchon,Kyongju,Mun-gyong,Andong,Kyongsan                                                        |
| Chollabuk     |           6 | Kunsan,Iksan,Namwon,Kimje,Chonju,Chong-up                                                                                           |
| Chungchongnam |           6 | Chonan,Sosan,Kongju,Nonsan,Asan,Poryong                                                                                             |
| Chollanam     |           5 | Mokpo,Sunchon,Yosu,Naju,Kwang-yang                                                                                                  |
| Kang-won      |           4 | Chunchon,Kangnung,Wonju,Tonghae                                                                                                     |
| Chungchongbuk |           3 | Chungju,Chongju,Chechon                                                                                                             |
| Cheju         |           1 | Cheju                                                                                                                               |
| Inchon        |           1 | Inchon                                                                                                                              |
| Kwangju       |           1 | Kwangju                                                                                                                             |
| Pusan         |           1 | Pusan                                                                                                                               |
| Seoul         |           1 | Seoul                                                                                                                               |
| Taegu         |           1 | Taegu                                                                                                                               |
| Taejon        |           1 | Taejon                                                                                                                              |
+---------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------+

 

select district, count(name), group_concat(name) from city where countrycode="KOR" group by district having count(name) <= 6 order by count(name) desc;
+---------------+-------------+-------------------------------------------+
| district      | count(name) | group_concat(name)                        |
+---------------+-------------+-------------------------------------------+
| Chollabuk     |           6 | Kunsan,Iksan,Namwon,Kimje,Chonju,Chong-up |
| Chungchongnam |           6 | Chonan,Sosan,Kongju,Nonsan,Asan,Poryong   |
| Chollanam     |           5 | Mokpo,Sunchon,Yosu,Naju,Kwang-yang        |
| Kang-won      |           4 | Chunchon,Kangnung,Wonju,Tonghae           |
| Chungchongbuk |           3 | Chungju,Chongju,Chechon                   |
| Cheju         |           1 | Cheju                                     |
| Inchon        |           1 | Inchon                                    |
| Kwangju       |           1 | Kwangju                                   |
| Pusan         |           1 | Pusan                                     |
| Seoul         |           1 | Seoul                                     |
| Taegu         |           1 | Taegu                                     |
| Taejon        |           1 | Taejon                                    |
+---------------+-------------+-------------------------------------------+

 

정렬 시 유의할 점

이전 글에서 오름차순(ASC), 내림차순(DESC) 정렬을 이용해 봤는데, 정렬 시 유의할 점이 있다.

ORDER BY에 의한 정렬을 수행할 때 행의 순서를 늘 같게 하려면, 정렬 키를 한 가지로(Unique 하게) 정해야 한다. 즉, 정렬 키가 같은 값의 행이 복수개 존재한다면, 그 행들의 순서는 매번 일정하지 않다.

 

select * from city where countrycode="KOR" order by district;
+------+------------+-------------+---------------+------------+
| ID   | Name       | CountryCode | District      | Population |
+------+------------+-------------+---------------+------------+
| 2357 | Kunsan     | KOR         | Chollabuk     |     266569 |
| 2352 | Iksan      | KOR         | Chollabuk     |     322685 |
| 2398 | Namwon     | KOR         | Chollabuk     |     103544 |
| 2393 | Kimje      | KOR         | Chollabuk     |     115427 |
| 2342 | Chonju     | KOR         | Chollabuk     |     563153 |
| 2380 | Chong-up   | KOR         | Chollabuk     |     139111 |
| 2361 | Mokpo      | KOR         | Chollanam     |     247452 |
| 2360 | Sunchon    | KOR         | Chollanam     |     249263 |
| 2370 | Yosu       | KOR         | Chollanam     |     183596 |
| 2397 | Naju       | KOR         | Chollanam     |     107831 |
| 2390 | Kwang-yang | KOR         | Chollanam     |     122052 |

위 예시처럼 같은 정렬 키(district)가 복수개 존재한다면 그 행들의 순서는 일정하지 않을 수 있다.

따라서 위 행들을 일정한 순서로 나열하기 위해서는 unique 한 정렬 키를 지정해야 한다.

order by district, name;

(사실, district만 정렬 키로 사용한 결과도 매 실행마다 같았다.)

 

종합하면 'ORDER BY, GROUP BY, HAVING'의 작성 순서는 다음과 같다.

SELECT ~ FROM ~ WHERE ~ GROUP BY ~ HAVING ~ ORDER BY ~
Comments