본문 바로가기
DB

[DB / Oracle] Chapter 5. SELECT문

by nyeoo 2023. 11. 28.

1. SELECT 문의 처리(PARSING) 순서

  • (+) : 있을수도 없을수도 있는 옵션
  • SELECT 컬럼명 -- ⑤┐ FROM 테이블명 -- ①┘ WHERE 조건절 -- ② + -- 조건에 맞는 애들만 메모리에 올려 GROUP BY 절 -- ③ + -- 그에 해당하는 애들을 그룹으로 묶어 HAVING 조건절 -- ④ + ORDER BY 절 -- ⑥ + -- 정렬에 관여하는 절

2. SELECT

  • 질의 결과 추출되는 속성 리스트를 열거함

▷ 집계함수(Aggragate Function) : 처리해야 할 데이터들 중 NULL이 존재한다면(포함되어 있다면)이 NULL은 제외한 상태로 연산을 수행

※ NULL : ORACLE 9i 까지는 NULL 을 가장 작은 값으로 간주했었으며, 현재 오라클에서는 NULL 을 가장 큰 값으로 간주함(정렬시 확인 가능). MSSQL은 NULL을 가장 작은 값으로 간주

함수 기능 사용 예
SUM() SUM(SAL) → 급여 합
AVG() 평균 AVG(SAL) → 급여 평균
COUNT() *1) 행(레코드)의 개수 카운트 COUNT(*) → 전체 행 개수 카운트
MAX() 최대값 MAX(SAL) → 급여 최대값
MIN() 최소값 MIN(SAL) → 급여 최소값
VARIENCE() *2) 분산 VARIENCE(SAL) → 급여 분산
STDDEV() *3) 표준편차 STDDEV(SAL) → 급여 표준편차

1) COUNT() : NULL은 카운트 대상에서 제외되므로 특정 컬럼을 조회하기보다 전체(*)를 조회하는 것이 일반적
2) SQRT(VARIANCE(SAL)) = STDDEV(SAL) → 분산의 제곱근이 표준편차
3) POWER(STDDEV(SAL),2) = VARIANCE(SAL) → 표준편차의 제곱이 분산

⚠️ 다중행의 레코드와 집계함수를 사용한 결과인 단일행의 레코드동시에 조회하는 구문은 사용불가 (GROUP BY를 사용하자!)

  SELECT ENAME, SUM(SAL)
  FROM EMP;
  --==>> 에러 발생(ORA-00937: not a single-group group function)

3. FROM

  • 질의에 어느 테이블이 사용되는지 열거함

4. WHERE

  • 질의의 조건을 작성

▶ 조건으로 사용할 수 있는 연산자들

연산자 사용 예
=, !=, <>, ^=, <, <=, >, >= SAL <10000
BETWEEN ~ AND ~ SAL BETWEEN 5000 AND 20000
IN(), NOT IN() SAL IN (3000, 5000, 7000)
LIKE ‘ ’ ENAME LIKE ‘박__' / ENAME LIKE ‘박%'
IS NULL, IS NOT NULL SAL IS NULL
AND, OR, NOT SAL> 3000 AND ENAME LIKE ‘박__'

▷ WILD CARD(CHARACTER)

문 자 기능 사용 예 설명
% 임의의 문자가 와일드카드로 표시되는 여러 위치에 나타날 수 있음을 지정 LIKE NAME ‘%영%’ ‘영’을 포함하는 이름을 NAME 컬럼에서 찾음
_ 모든 문자가 나타날 수 있는 단일 위치를 지정 LIKE NAME ‘__영’ ‘영’으로 끝나는 이름을 NAME 컬럼에서 찾음

5. GROUP BY

  • 속성값끼리 그룹화하여 그룹이 만들어짐
  • 다중행의 레코드와 단일행의 레코드를 동시에 조회하는 구문이 사용가능해짐
  • GROUP BY를 사용한 SELECT 구문에는 GROUP BY에서 사용한 속성과 집계함수만 나올 수 있음

⚠️ CASE를 사용 할 때, 데이터형식을 맞추는 것을 유의해야 한다면 GROUP BY에서는 그룹지을 때 사용한 방식을 그대로 인용하여 SELECT 에서 사용해야함을 유의

SELECT CASE GROUPING(TO_CHAR(HIREDATE, 'YYYY')) WHEN 0 
THEN TO_CHAR(EXTRACT(YEAR FROM HIREDATE)) ELSE '전체'
END "입사년도", COUNT(*) 인원수
FROM TBL_EMP
GROUP BY CUBE(TO_CHAR(HIREDATE, 'YYYY'))
ORDER BY 1;
--==>> 오류 발생

▶ 그룹함수 : ROLLUP, CUBE, GROUPING SETS

함수 기능 사용 예
ROLLUP GROUP BY절에 의해서 그룹 지어진 집합 결과에 대해서 좀 더 상세한 정보를 반환. 데이터의 총계를 구할 수 있음 ROLLUP(A, B, C) → (A, B, C) / (A, B) / (A) / ()
CUBE ROLLUP 보다 더 자세한 결과를 반환 CUBE(A, B, C) → (A, B, C) / (A, B) / (A, C) / (B, C) / (A) / (B) / (C) / ()
GROUPING SETS ROLLUP은 묶음방식이 다소 모자랄 때가 있고, CUBE는 다소 지나칠 때가 있기 때문에 조회하고자 하는 그룹만 GROUPING SETS를 이용하여 선택적으로 묶음 가능 GROUPING SETS((A, B, C), (A, B), (A), ()) = ROLLUP(A, B, C) ``GROUPING SETS((A, B, C), (A, B), (A, C), (B, C), (A), (B), (C), ())= CUBE(A, B, C)

▷ 그룹함수와 함께 사용하는 함수들 : GROUPING, GROUPING_ID

  • GROUPING(컬럼명1) : GROUP BY절에 ROLLUP 등으로 그룹화하여 소계나 합계로 조회된 행일경우 1을 리턴하고, 그렇지 않으면 0을 리턴함. GROUP BY로 그룹화된 데이터들에서 NULL을 구분가능하게 함. 파라미터로 하나의 컬럼만 사용가능
  • GROUPING_ID(컬럼명1, 컬럼명2,..) : GROUPING과 같은 기능을 가지며, 다수의 컬럼에 대해 GROUPING 값을 확인한 후 비트방식으로 2진수의 값을 10진수 형태로 반환함. 예를 들어, 컬럼명1 값은1, 컬럼명2 값은 0이라면 2진수 10 이므로 10진수로 변환하여 2를 반환함
  • GROUPING, GROUPING_ID 함수는 SELECT 절HAVING 절에서 사용할 수 있음
  • HAVING GROUPING_ID(컬럼명1, 컬럼명2) != 1 을 이용해서 소계를 제외하고 조회가능

6. HAVING

  • GROUP BY 절의 결과 나타나는 그룹을 제한하는 역할(검색 조건에는 집계함수가 와야함)

⚠️ HAVING 사용시 유의할 부분

--①
SELECT DEPTNO, SUM(SAL)
FROM EMP
GROUP BY DEPTNO
HAVING SUM(SAL) < 10000
AND DEPTNO IN (20, 30);
--②
SELECT DEPTNO, SUM(SAL)
FROM EMP
WHERE DEPTNO IN (20, 30)    -- OR
GROUP BY DEPTNO
HAVING SUM(SAL) < 10000;

① EMP 테이블 전체를 1차로 메모리에 퍼올림 + 뒷부분 실행
② WHERE절이 있을 경우, 테이블에서 WHERE 절까지 1차로 메모리에 퍼올림 + 뒷부분 실행
→ 쿼리문의 효율성이 극명하게 다름. 두 번째의 방식으로 쿼리문을 구성하는 것이 바람직함

7. ORDER BY

  • 실행 결과를 특정기준에 따라 순서대로 정렬하여 출력할때 사용
  • DESC』 키워드는 내림차순, 『ASC』 오름차순 (『ASC』 키워드는 생략가능)
  • ex. ORDER BY DEPTNO, SAL DESC
    → ⚠️ DEPTNO(부서번호)는 오름차순, SAL(급여)는 내림차순으로 정렬됨에 주의
  • ex. ORDER BY 1, 3
    → 추출될 컬럼들 중 1번 컬럼을 오름차순 정렬 후 3번 컬럼을 오름차순 정렬
  • ORDER BY가 SELECT 보다 파싱순서가 후순위 이므로 SELECT 의 별칭사용 가능