'MySQL GROUP BY'에 해당되는 글 1건

  1. 2013.01.18 GROUP BY 4
posted by changhozz 2013. 1. 18. 11:48

이번엔 SQL기법중 GROUP BY기법과 내부함수에 대하여 알아보자.

1.GROUP BY
GROUP BY란 특정 칼럼을 기준으로 같은 값을 가지는 행들을 그룹별로 모아 자료를 가져오는 것이다.
쉽게말해서, 중복된 여러개의 값들 중 대표선수 한명만 뽑겠다는 뜻으로 보면 될 것이다.

예시를 보면서 설명하도록 해보겠다.

위와 같이 사람들이 좋아하는 축구선수 목록 테이블인 tb_soccer_player가 있다고 할때,
방금 설명한 내용대로 축구선수의 name을 GROUP BY 해보도록 하겠다.


Query :  SELECT * FROM tb_soccer_player GROUP BY name;

result :

결과를 보게되면, 원래 테이블은 8개의 행이였는데 5개의 행으로 줄어든 것을 볼 수 있다.
이유는 C.Ronaldo, Kaka, Messi는 값이 2개씩 존재했기 때문에, 그룹화 하여 단 한개의 데이터로 취급한 것 이다.

그렇다면 축구선수의 num으로 GROUP BY를 해봤을 경우를 예상해보자.

Query :  SELECT * FROM tb_soccer_player GROUP BY num;

result : 

예상대로 num중 7,9,10만 출력되는 것을 볼 수 있다.
8개의 행들 중 num 칼럼은 모두 7,9,10들 뿐이었기 때문이다.
그런데 여기서 7번에는 ji-sung도 있고, 10번에는 Zidane도있는데 왜 C.Ronaldo와 Messi가 선택되었을까? 
우리가 따로 정렬에 대한 정보를 입력하지 않았다면 GROUP BY는 내부적으로 시컨스를 기준으로 정렬(sorting)이 이루어진다.  따라서 id값이 작은 순서대로(먼저 들어온 데이터 순) 정렬이 되었기 때문에,
뒤늦게 들어온 ji-sing과 Zidane은 밀려버린 것 이다.


2.HAVING

지금까지는 조건이 없는 GROUP BY문들이었다.
평소 어떤 쿼리를 작성할때 조건을 달고싶었다면 WHERE절을 이용하였는데, GROUP BY에서의 조건은
WHERE로 처리하지 않고 HAVING절을 사용한다. 

그럼 HAVING절을 이용하여 GROUP BY 해보도록 하겠다.
먼저 조건을 주기위해 tb_soccer_player테이블에 선수 몸값 칼럼을 추가해보겠다.



여기서,
축구선수들 중 몸 값이 400이상인 선수들의 목록을 그룹화 하여 보고싶다면,


Query : SELECT * FROM tb_soccer_player GROUP BY name HAVING price > 400; 

result : 


이러한 결과가 나오게 되는 것 이다.


이번엔 조금더 실질적으로 사용되는 예들을 들어보겠다. 
 
집계함수를 사용하는 것인데, 우선 집계함수에는 어떠한 것들이 있는지 알아보도록 하겠다.

3. 집계함수

집계란 이미 계산 된 것들을 모아서 계산하는 것을 말한다. 즉, 이미 계산된 결과를 어떤 기준으로
그룹화 하는 함수를 집계함수라고한다.

그렇다면 어떤 집계함수들이 있는지 확인해보자.


집계함수 

의미 

count (필드명)

null값이 아닌 레코드의 개수 

sum(필드명) 

필드명의 값들의 합계 

avg(필드명) 

필드명의 값들의 평균 

max(필드명)  필드명의 값들 중 최대값 
 min(필드명)

필드명의 값들 중 최소값 

count(*)   테이블에 속하는 레코드의 개수


합수를 사용한 예를들기위해 새로운 테이블 tb_employee를 만들었다.
현재 tb_employee 칼럼으로는 dept(부서), position(직책), headcnt(인원수), salary(급여)가 존재한다.


ex.1) 각 부서당 몇개의 직책이 있는지 알고싶다.

Query : SELECT dept,count(position) position_cnt FROM tb_employee GROUP BY dept;

result : 


ex.2) 각 부서당 전체사원의 수를 알고싶다.

Query : SELECT dept, sum(headcnt) from tb_employee GROUP BY dept;

result :  


ex.3) 직책별로 평균 급여를 알고싶다.

Query : SELECT position, CEILING(avg(salary)) salary_avg from tb_employee GROUP BY position;

result : 


(여기서 CEILING()은 내장함수로 소수점을 버려준다. )


앞으로 공부를 하면서 더 나은 예제가 있다면 또 다시 정리해보자.



'MySQL' 카테고리의 다른 글

JOIN  (0) 2013.01.11