[필기정리]Day56-2 - Select 명령문의 절(Clause) : group by, having, select, order by 등

DB/MySQL

2020. 9. 10. 12:34

# Select 명령문을 구성할 때 규칙 및 주의할 점
- 각 select 명령문은 select와 from이라는 절을 가지기 때문에 적어도 2개의 절을 가지고 있다.

  그리고 where, group by, order by 같은 절은 선택적으로 사용된다.


- 절의 순서는 고정되어 있다.

  예를 들면, group by절은 where 또는 from절 앞에 올 수 없다.

  그리고 order by절이 사용된다면 이 절은 항상 가장 나중에 사용된다.


-  having절은 group by 절이 사용되어야 만이 사용할 수 있다.

 

// Tip : group by의 조건을 having을 사용하는 것이지

          group by가 있다고 해서 where를 절대적으로 사용하지 못하는 것이 아니다.

- 정확한 select 명령문의 사용

select ... 
from ... 
order by ... 

select ... 
from ... 
group by ... 
having ... 

select ... 
from ... 
where ...


# select 명령문 모든 절을 포함한 수행 과정
Q1. 등록 테이블("FEE")에서 장학금을 지급 받은 학생의 학번과 장학금 내역을 출력하라.
A.

select stu_no, jang_total from fee where jang_total > 0;


Q2. 등록 테이블("FEE")에서 장학금을 1,000,000 이상 지급 받은 학생 중에서

      2회 이상 지급받은 학생의 학번과, 지급받은 횟수를 학번 내림차순으로 출력하라.
A.

select stu_no, count(*) from fee where jang_total >= 1000000 group by stu_no having count(*) > 1 order by stu_no desc; 

// Tip : count()는 집합함수로 grouping한 함수에만 사용이 가능하다.


SQL은 입력된 명령문과 다르게 절의 순서를 변경한다.
각 절이 수행되는 순서는

②(FROM절) -> ③(WHERE절) -> ④(GROUP BY절) -> ⑤(HAVING절) -> ①(SELECT절) -> ⑥(ORDER BY절)

순으로 처리가 진행된다.

 

각 절이 수행되면 0 또는 그 이상의 행과 1 또는 그 이상의 열로 구성된 하나의 결과 테이블(임시 테이블)이 생성된다.

첫 번째 절을 제외한 모든 절은 0 또는 그 이상의 행과 1 또는 그 이상의 열로 구성된 테이블을 가진다는 것이다.

 

첫 번째 절은 데이터베이스로부터 데이터를 찾아내고,

FROM 절은 데이터베이스로부터 하나 이상의 테이블을 입력으로 취한다.

다음 절의 입력으로 사용되는 이러한 테이블을 중간 결과 테이블(intermediate result table)이라 한다. 

SQL은 사용자에게 중간 결과 테이블을 보여주지는 않고 최종 결과 테이블만 보여 준다.

 

SQL은 여기서 설명한 것과 같이 SELECT 명령문을 처리하지는 않고 

실제적으로 처리 속도를 증가시키기 위해서 가능하다면 필요한 만큼 동시에 절들을 처리한다.

- from 절 : 테이블을 불러옴 
  From 절에서 FEE 테이블만 사용되었다. 

  SQL은 이 테이블에서만 작업을 수행한다는 것이다.

  이 절의 중간 결과 테이블은 FEE 테이블에서

  학번, 등록년도, 학기, 장학코드, 장학금액에 대한 정확한 자료는 다음과 같다.

- where 절 : 조건절
  조건으로 jang_total >= 1000000 이라는 where 절이 사용된다면

  jang_total 열에 있는 값이 1000000원 이상이 되는 모든 행은 조건을 만족하게 된다.

- group by 절 : 기준데이터를 기준으로 그룹 묶어줌
  group by 절은 그룹 별로 검색을 할 때 사용된다.

  group by절을 사용할 때는 그룹 함수를 같이 사용해야 한다.

대표적 그룹 합수 종류 설명
 count() 개수
 max() 최대값
min() 최소값
avg() 평균
sum() 총 합

// Tip : group by절에서만 그룹 함수를 사용할 수 있다!

 

ex) 학번 그룹

select stu_no, count(*) from fee where jang_total >= 1000000 group by stu_no;


 위 예제에서는 동일한 학번을 가진 행을 하나의 그룹으로 묶고 

 동일한 행의 개수를 count(*) 열에 출력하는 예제이다.

 

 즉, fee 테이블에는 장학금은 1,000,000원 이상 받은 학생 중

 stu_no로 그룹을 만들어 각 학생(stu_no) quffh 1,000,000원이상 장학금을 받은 횟수를 출력하는 예제이다.

 이와 같이 group by절을 사용하여 하나의 테이블을 그룹으로 분류하여 데이터를 처리할 수 있다.

- having 절  : group by에 대한 조건 - ∴ group by 없이 사용 불가! 
  having 절과 where 절을 서로 비교할 수 있는데,

  그 차이점은 where 절은 from 절에서 생성된 중간 테이블에서 동작하고,

  having 절은 group by 절에서 생성된 중간 테이블에서 동작한다.

  사실 수행된 과정은 동일하다.

  having 절을 포함시켰을 때 sql은 조건을 참조하여 행을 선택한다.

  이러한 경우에 조건은 다음과 같다.

count(*) > 1

 

ex)

select stu_no, count(*) from fee where jang_total >= 1000000 group by stu_no having count(*) > 1;

위의 예제는 1,000,000원 이상 장학금을 2번 이상 받은 학생의 stu_no와 횟수를 출력하는 예제이다.

having 절을 이용하여 group by의 결과로 만들어진 중간 테이블에서 

count(*) 값이 1 보다 큰 행만 선택하여 출력하고 있다.


- select 절 : 칼럼 지정
  select 절은 최종 결과 테이블에 표현될 열을 지정하기 위해서 사용된다. 

  다시 말하면 select 절은 열을 선택하는 것이다.
  학사 관리 예제의 fee 테이블은 stu_no, fee_year, fee_term, fee_enter 등 11개의 열로 구성된다.

  따라서 select 절을 이용하여 fee 테이블 중에서 stu_no와 fee_year만 선택하여 출력할 수 있다.

select stu_no, fee_year from fee;


  select 절은 다른 절을 이용해 만들어진 중간 결과 테이블에서

  사용자가 보고 싶은 절을 선택하여 출력할 수 있다.

 

  아래 예제는 fee 테이블에서 장학금을 1,000,000원 이상 받은 학생의

  stu_no와 fee_year, fee_term을 출력하는 예제이다.

select stu_no, fee_year, fee_term from fee where jang_total >= 1000000;

 

- order by 절 : 정렬
  order by 절은 마지막으로 수행되는 절로 중간 결과 테이블의 내용에 영향을 주지 않는다.

  그러나 마지막까지 선택된 행을 정렬한다.

 

  따라서 stu_no 열에 있는 데이터는 order by절에 의해서 정렬된다.

  select 절에서 나온 결과 값은 입력된 데이터 순으로 출력되었으므로

  정렬을 원하면 order by절을 사용한다.

  

  결과 값은 학번 내림차순이므로 결과 값이 달라질 것이다.

  사용자에게 보이는 최종 결과는 다음과 같다.

select stu_no, count(*) from fee where jang_total >= 1000000 group by stu_no having count(*) > 1 order by stu_no desc;


# select 명령문 일부 절을 포함한 절을 포함한 수행 과정
   select 명령문에서

   group by, having 절이 없는 명령문이 수행되는 과정을 보여주기 위해서 두 번째 예제를 살펴보자.

Q1. 수강신청 테이블(attend)에서

     2006년도 1학기에 수강 신청한 학생의 학번과 수강년도, 학기, 교과목코드, 교수코드를

     교수코드 오름차순으로 나타내어라.
A.

select stu_no, att_year, att_term, sub_code, prof_code from attend where att_year = '2006' and att_term = 1 order by prof_code; 

 

- from 절
  from 절에서 attend 테이블만 사용

- where 절
  조건으로 

att_year = '2006' and att_term=1

 이라는 where 절이 사용된다면 이 두 가지 조건이 모두 만족한 행이 결과 값으로 출력되며

- group by절
  group by 절을 사용하지 않았으므로 중간 결과는 변하지 않고 그대로 유지된다.

- having 절
  having 절을 사용하지 않았으므로 중간 결과는 변하지 않고 그대로 유지된다.

- select 절
  select 절에서 stu_no, att_year, att_term, sub_code, prof_code 열을 출력하고

- order by 절
  order by 절은 마지막으로 수행되는 절로 중간 결과 테이블의 내용에 영향을 주지 않는다.

  그러나 마지막까지 선택된 행을 정렬한다.

 

  order by prof_code는 오름차순 정렬인 asc(ending)이 생략된 경우로

  교수코드를 우선적으로 오름차순 정렬하여 결과 값을 출력한다.
 

  만약 order by 의 정렬 대상의 결과 값에 null 값이 존재한다면

  mysql에서는 null 값이 가장 적은 값이 되어 오름차순 정렬에는 맨 처음에 출력되고,

  내림차순인 경우에는 맨 마지막에 출력된다.

 

// Tip : 위의 해석 순서를 반드시 기억하기!

728x90