SQLD/SQL 기본과 활용

SQL) GROUP BY 절, HAVING 절, ORDER BY절, SELECT 문장 실행 순서

DevPing9_ 2020. 8. 20. 17:13

# 실행 순서 : FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

  (옵티마이저가 SYNTAX, SEMANTIC 에러를 점검하는 논리적 순서)

  (물리적 순서는 실행계획에 의해 정해짐)

 

1. GROUP BY절

 

   # GROUP BY 절은 FROM, WHERE절 뒤에 위치하며, 데이터들을 소그룹에 대한 항목별로 통계 정보를 얻을 때 추가로 사용된다.

 

/*
SELECT [DISTINCT] COL1 [ALIAS]
FROM TAB1
[WHERE condition1]
[GROUP BY exp1]
[HAVING condition2]
[ORDER BY exp2 [ASC | DESC]];
*/


# 집계함수는 WHERE 절에 올 수 없다
# 실행순서 : FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY
# HAVING 절은 GROUP BY 절의 조건을 담음
# 즉, WHERE에서 걸러진 GROUP을 HAVING으로 다시 거르는 작업
# 추가) GROUP BY 절에는 SELECT 절에서 정의된 ALIAS를 사용할 수 없다



SQL> SELECT POSITION
           ,COUNT (*) AS TOTAL
           ,COUNT (NFS) AS NOT_FORSALE
           ,MAX (HEIGHT) AS MAX_HEIGHT
           ,MIN (HEIGHT) AS MIN_HEIGHT
           ,ROUND (AVG (HEIGHT), 2) AS AVG_HEIGHT
     FROM PLAYER
     GROUP BY POSITION;
     
# 실행결과 (GROUP BY에 의해 묶인 그룹별로 집계함수가 작동하는 것을 볼 수 있음)
   
POSITION        TOTAL       NOT_FORSALE      MAX_HEIGHT      MIN_HEIGHT      AVG_HEIGHT
------------------------------------------------------------------------------------
                       3                0                                         
GK                   46               11                    197                  182                 188.82
DF                  177               10                    190                  176                 184.23
FW                  120               6                     194                  167                 176.69
MF                  185               3                     188                  167                 178.88

 

 

2. HAVING 절

  - GROUP BY 연산 후 HAVING절에 의해 필터링 됨

  - 왠만하면 WHERE 절에서 필요한 데이터만 추출하여 GROUP BY 연산을 하는 것이 효율적임

  - 그룹별 집계함수 적용은 HAVING절을 이용해야 함. (WHERE절에서 사용 불가능, 오류발생)

/*
SELECT [DISTINCT] COL1 [ALIAS]
FROM TAB1
[WHERE condition1]
[GROUP BY exp1]
[HAVING condition2]
[ORDER BY exp2 [ASC | DESC]];
*/


SQL> SELECT TEAM_NAME, COUNT(*) AS TOTAL 
			FROM PLAYER
			WHERE TEAM_NAME IN ('삼성버거킹', '롯데맥도날드')
            GROUP BY TEAM_NAME;
            
SQL> SELECT TEAM_NAME, COUNT(*) AS TOTAL 
			FROM PLAYER
            GROUP BY TEAM_NAME
            HAVING TEAM_NAME IN ('삼성버거킹', '롯데맥도날드');
    
# 실행결과 (결과는 같으나 GROUP BY연산의 결과 데이터들의 갯수가 차이가 남)
TEAM_NAME        TOTAL
-------------------------
삼성버거킹            85
롯데맥도날드          70



 

 

3. ORDER BY절

 - DEFAULT 정렬값은 오름차순(ASC)

 - 날짜형 데이터 타입은 과거가 작은 값

 - NULL값은 Oracle에서는 가장 큰 값, SQL Server에서는 가장 작은 값

 - SELECT절에서 언급되지 않은 다른컬럼 사용가능 (행 단위 모든칼럼 단위 데이터 사용가능) 

/*
SELECT [DISTINCT] COL1 [ALIAS]
FROM TAB1
[WHERE condition1]
[GROUP BY exp1]
[HAVING condition2]
[ORDER BY exp2 [ASC | DESC]];
*/

SQL> SELECT TEAM_NAME, COUNT(*) AS TOTAL 
			FROM PLAYER
			WHERE TEAM_NAME IN ('삼성버거킹', '롯데맥도날드')
            GROUP BY TEAM_NAME;
            
SQL> SELECT TEAM_NAME, COUNT(*) AS TOTAL 
			FROM PLAYER
            GROUP BY TEAM_NAME
            HAVING TEAM_NAME IN ('삼성버거킹', '롯데맥도날드');
    
# 실행결과 (결과는 같으나 GROUP BY연산의 결과 데이터들의 갯수가 차이가 남)
TEAM_NAME        TOTAL
-------------------------
삼성버거킹            85
롯데맥도날드          70



 

 

 

 

 

 

728x90