본문 바로가기

Database/MySQL

[데이터베이스(강의)] 8. SQL로 데이터 조회 (group by, aggregate function, order b)

 

 

* ORDER BY

 - 조회 결과를 특정 attribute(s) 기준으로 정렬하여 가져오고 싶을 때 사용한다.

 - default 정렬 방식은 오름차순이다

 - 오름차순 정렬은 ASC로 표기한다.

 - 내림차순 정렬은 DESC로 표기한다.

 

 


 

 

 - 임직원들의 정보를 연봉 순서대로 정렬해서 알고 싶다.

 

SELECT * FROM employee ORDER BY salary;

 

=> 기본이 오름차순 (ASC)

 

 

SELECT * FROM employee ORDER BY salary DESC;

 

 

 

 

 - 임직원들의 정보를 연봉 순서대로 정렬해서 알고 싶다.

 + 부서별정렬

 

SELECT * FROM employee ORDER BY dept_id ASC, salary DESC;

 

=> dept_id 기준 내림차순 정렬 이후 salary 기준 오름차순 정렬

                         NULL값이 가장 먼저 (MySQL)


 

* aggregate function

 - 여러 tuple들의 정보를 요약해서 하나의 값으로 추출하는 함수

 - 대표적으로 COUNT, SUM, MAX, MIN, AVG 함수가 있다.

 - (주로) 관심있는 attribute에 사용된다.        e.g.) AVG(salary), MAX(birth_date)

 - NULL값들은 제외하고 요약 값을 추출한다.

 


 

 

- 임직원 수를 알고 싶다.

 

 

SELECT COUNT(*) FROM employee

                     튜플의 수

 

 

SELECT COUNT(position) FROM employee;

 

=> position에 중복이 있지만 모두 count한다.

 

 

 

SELECT COUNT(dept_id) FROM employee;

 

=> dept_id가 NULL인 튜플은 제외하고 count 

 

 

따라서 (*)로 지정해줘야 정확한 튜플의 갯수를 가져올 수 있다.

 

 


 

 

- 프로젝트 2002에 참여한 임직원 수최대 연봉최소 연봉평균 연봉을 알고 싶다.

 

 

SELECT COUNT(*), MAX(salary), MIN(salary), AVG(salary)

FROM employee E JOIN works_on W ON W.empl_id = E.id

WHERE W.proj_id = 2002;

 


 

* GROUP BY

 - 관심있는 attribute(s) 기준으로 그룹을 나눠서 그룹별로 aggregate function 을 적용하고 싶을 때 사용.

 - grouping attribute(s) : 그룹을 나누는 기준이 되는 attribute(s)

 - grouping attribute(s) 에 NULL값이 있을 때는 NULL값을 가지는 tuple까지 묶인다.

 

 

 

- 각 프로젝트에 참여한 임직원 수 최대 연봉 최소 연봉 평균 연봉을 알고 싶다.

 

 

SELECT W.proj_id, COUNT(*), MAX(salary), MIN(salary), AVG(salary)

FROM employee E JOIN works_on W ON W.empl_id = E.id

GROUP BY W.proj_id;

 

=> SELECT 뒤에 proj_id를 적어줘야 한다. 이걸 기준으로 그룹을 묶을거니까!!

      group by 에서 기준이 되는 attribute(s)는 반드시 SELECT 뒤에 적어줘야함.

 


 

 * HAVING

 - GROUP BY 와 함께 사용한다.

 - aggregate function의 결과값을 바탕으로 그룹을 필터링하고 싶을 때 사용한다.

 - HAVING절에 명시된 조건을 만족하는 그룹만 결과에 포함된다.

 

 

 

- 프로젝트에 참여한 인원이 4명 이상인 프로젝트들에 대해서,

   각 프로젝트에 참여한 임직원 수 최대 연봉 최소 연봉 평균 연봉을 알고 싶다.

 

 

SELECT W.proj_id, COUNT(*), MAX(salary), MIN(salary), AVG(salary)

FROM employee E JOIN works_on W ON W.empl_id = E.id

GROUP BY W.proj_id

HAVING COUNT(*) >= 4;

 

=> grouping 한 결과에서 count를 기준으로 조건이 추가됨.

 


 

 

- 각 부서별 인원수를 인원 수가 많은 순서대로 정렬해서 알고 싶다.

 

 

 

SELECT dept_id, COUNT(*) AS empl_count

FROM employee 

GROUP BY dept_id

ORDER BY empl_count DESC;

 

 

=> grouping의 기준이 되는 dept_id가 NULL인 경우에는

         NULL인 tuple끼리 묶어서 count를 하게 된다.

 

 


 

( group by + order by )

 

- 각 부서별 성별 인원수를 인원 수가 많은 순서대로 정렬해서 알고 싶다.

 

 

SELECT dept_id, sex, COUNT(*) AS empl_count

FROM employee

GROUP BY dept_id, sex

ORDER BY empl_count DESC;

 

 


 

( group by + having + subquery )

 

 

- 회사 전체 평균 연봉보다 평균 연봉이 적은 부서들의 평균 연봉을 알고 싶다.

             subquery 이용

 

 

더보기

SELECT dept_id, AVG(salary) AS avg_salary

FROM employee 

GROUP BY dept_id

HAVING (SELECT AVG(salary) FROM employee) > avg_salary;

 

SELECT dept_id, AVG(salary)

FROM employee 

GROUP BY dept_id

HAVING AVG(salary)  <  (

                             SELECT AVG(salary) FROM employee

                  );

 

 


 

( group by + order by + having + subquery )

 

 

- 각 프로젝트별로 프로젝트에 참여한 90년대생들의 수이들의 평균 연봉을 알고 싶다.

 

 

 

SELECT proj_id, COUNT(*), ROUND(AVG(salary), 0)

FROM employee E JOIN works_on W ON E.id = W.empl_id

WHERE E.birth_date BETWEEN '1990-01-01' AND '1999-12-31'

GROUP BY W.proj_id;

 

 

* ROUND(number, [decimals])

 - number : 반올림할 숫자

 - decimals : 소수점 이하 자릿수 지정, 생략가능


 

- 각 프로젝트별로 프로젝트에 참여한 90년대생들의 수 이들의 평균 연봉을 알고 싶다.

  + proj_id 기준 정렬

 

SELECT proj_id, COUNT(*), ROUND(AVG(salary), 0)

FROM employee E JOIN works_on W ON E.id = W.empl_id

WHERE E.birth_date BETWEEN '1990-01-01' AND '1999-12-31'

GROUP BY W.proj_id

ORDER BY W.proj_id;

 


 

 

- 프로젝트 참여 인원이 4명 이상인 프로젝트에 한정해서,  

  각 프로젝트별로 프로젝트에 참여한 90년대생들의 수 이들의 평균 연봉을 알고 싶다.

  

 

 

SELECT proj_id, COUNT(*), ROUND(AVG(salary), 0)

FROM employee E JOIN works_on W ON E.id = W.empl_id

WHERE E.birth_date BETWEEN '1990-01-01' AND '1999-12-31'

GROUP BY W.proj_id

HAVING COUNT(*) >= 3    => group을 필터링, 즉 전체가 아닌 90년대생들의 count를 필터링하게됨

ORDER BY W.proj_id;

 

 

** HAVING 이 아닌 WHERE절에 조건이 추가되어야 함.

 

 

SELECT proj_id, COUNT(*), ROUND(AVG(salary), 0)

FROM employee E JOIN works_on W ON E.id = W.empl_id

WHERE E.birth_date BETWEEN '1990-01-01' AND '1999-12-31'

                       AND W.proj_id IN ( SELECT proj_id FROM works_on 

                                                       GROUP BY proj_id HAVING COUNT(*) >= 4 )

GROUP BY W.proj_id

ORDER BY W.proj_id;

 

 

 

 

* subquery 결과

더보기

 

SELECT proj_id FROM works_on GROUP BY proj_id HAVING COUNT(*) >= 4

 

 

 

=> 어떤 조건이냐에 따라서 WHERE 절 / HAVING 절에 조건을 지정할지 달라지니 조심 **

 


 

[ SELECT ]

 

6. SELECT attribute(s) or aggregate function(s)

1.  FROM table(s)

2. [ WHERE condition(s) ]                     _ FROM 절의 table 에 대한 필터링

3. GROUP BY group attribute(s) ]

4. [ HAVING group condition(s) ]          _ grouping 이후 필터링

5. ORDER BY attribute(s) ];

 


 

* SELECT 실행 순서

 - select 쿼리에서 각 절(phrase)의 실행 순서는 개념적인 순서이다.

 - select 쿼리의 실제 실행 순서는 각 RDBMS에서 어떻게 구현했는지에 따라 다르다.

 

 

 

* 이 내용은 MySQL 기준 *


 

 

https://www.youtube.com/watch?v=rG8yQ7yKGTE&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=9