5월 25일 화요일 (11일차) - 서브쿼리ㅇ

@_@·2021년 5월 25일
0

Database

목록 보기
20/28

<목차>
(단일 행 서브쿼리)
ㅇ WHERE절에서
ㅇ HAVING절에서
ㅇ 단일 행 서브 쿼리에서의 NULL 값


ㅇ 참고자료 <Do it! 오라클로 배우는 데이터베이스 입문>



ㅇ 실험) Abel이라는 사원보다 더 많은 급여를 받는 사원의 이름과 급여를 출력하시오.

  • 아벨이라는 사원의 급여를 모르니까 먼저 찾아줘야겠지 => 1차 웨어절 : last_name = 'Abel' 으로 급여 출력
  • 11000임을 알았어. 이걸로 다시 조건에 맞는 사원 이름, 급여 출력 => 2차 웨어절 : salary>11000
  • 셀렉트 문장을 2번 수행해야 하는 불편함이 발생
  • 한 번의 문장으로 처리할 수 있는 방법 => 서브쿼리
SELECT last_name
FROM employees
WHERE salary > ( SELECT salary
		FROM employees
		WHERE last_name = 'Abel')


ㅇ SUBQUERY 서브쿼리

  • GROUP BY 절에서는 사용 불가 ★★ (다른 절은 다 가능)
  • SELECT, ORDER BY 절에 사용하는 서브쿼리는 꽤 어려워서 이번 과정에서는 배우지 않을 거야
  • 오늘 WHERE절,HAVING절 / 내일 FROM절
  • 서브쿼리가 먼저 실행되고, 서브쿼리 실행 결과값을 메인쿼리가 받아서 사용
    (물론 고급기능들로 메인커리를 서브쿼리로 보내주는 것도 있어)
  • 서브쿼리 안에 서브쿼리가 더 들어갈 수도 있어. 현업에서는 2단계 정도 더 타고 가
  • 장점 : 조인을 대체할 수 있어, 셀프조인은 웬만하면 서브쿼리로 가능
    • 조인은 2개 테이블을 하나로 매칭하는 작업 추가돼서 성능 떨어져
    • 서브쿼리 쓸 수 있으면 서브쿼리를 쓰는 게 나아
      CF. 조인과 정렬은 필요악
      : 어쩔 수 없으면 쓰지만, 안 쓸 수 있으면 안 쓰는 게 나아

ㅇ WHERE절과 HAVING절에서의 서브쿼리

  • 웨어절, 해빙절 공통점 : 조건문이다. / (컬럼/그룹함수(컬럼))+연산자+값으로 구성 (즉, 사용법이 같다.)
  • 웨어절, 해빙절에서 사용되는 서브쿼리는 '값'의 역할을 수행해
  • 서브쿼리의 결과를 값으로 사용을 한다
  • 즉, 특정 값을 모르고 있을 때 사용하면 좋아

ㅇ 서브쿼리 사용 지침 (WHERE절과 HAVING절에서)

  • 서브 쿼리를 괄호로 묶어주기 : 메인 쿼리와 구분하고, 하나의 값임을 보여주기 위해
  • 비교 조건의 오른쪽에 서브 쿼리
    ( 컬럼 + 연산자 + '값'<-여기에 서브쿼리 )
    • 실행 측면에서는 '타입'만 같으면 되긴 해
    • 즉, 컬럼 이름 달라도 상관없긴 해... ㅋㅋ
    • 근데 대부분 넘겨주는 컬럼과 받아들이는 컬럼이 같아
    • 다르면 처리는 되지만 의미가 없잖아. 예)사원번호=급여
  • ORDOER BY 절에는 될 수 있으면 안 쓰는 걸 권장
    • 성능이 떨어져
      : 오더바이절은 출력이 되는 결과값을 정렬하는 역할인데, 서브쿼리는 출력이 되는 값이 아니라 '사용'되는 값이야.
      출력 되지도 않는 값을 굳이 정렬시켜야 할 필요 있어?
    • 그러나 FROM절에서 사용되는 서브쿼리에서는 오더바이절이 굉장히 중요해져
    • 탑N 분석 : 상위 3사람, 하위 3사람 이런 거
  • 단일 행 서브쿼리에는 단일 행 연산자를 사용
    다중 행 서브 쿼리에는 다중 행 연산자 사용 ★★ : 연산자 주의해서 사용하기

ㅇ 단일 행/다중 행 서브쿼리

  • 단일 행 서브쿼리: 하나의 결과를 돌려주는 서브쿼리
    • 단일연산자 사용 : =, <, > 등
  • 다중 행 : 여러 개의 결과를 돌려주는 서브쿼리
    • 복수연산자 사용 : IN, >ANY, <ALL 등

CF. 더 크게 구분 지어주면

  • 단일 컬럼 서브쿼리 ⊃ 단일 행, 다중 행
  • 다중 컬럼 서브쿼리 : 여러 컬럼을 하나의 행으로 묶어서 a,b (많이 쓰이진 않아)

ㅇ 서브쿼리 작성 패턴

  • 1 내가 뭘 모르는지 : 내가 모르는 값을 어떤 컬럼을 통해 찾을 것인지
  • 2 누가 받는지 : 서브쿼리가 넘겨주는 값을 어떤 컬럼이 받아들이는지
  • 3 어떤 연산자를 사용할 건지 : 단일/복수


(단일 행 서브쿼리)

ㅇ WHERE절에 서브쿼리 사용

  • 실습1) 141번과 업무가 같은 사원들
SELECT last_name, job_id
FROM employees
WHERE job_id = ( SELECT job_id
		FROM employees
		WHERE employee_id=141 )
  • 실습2) 141번과 업무가 같으면서 143번보다 급여를 많이 받는 사원들
SELECT last_name, job_id, salary
FROM employees
WHERE job_id = ( SELECT job_id
		FROM employees
		WHERE employee_id=141 )
AND salary > ( SELECT salary
		FROM employees
		WHERE employee_id=143 )

ㅇ 서브쿼리에서 그룹함수 사용

  • 어제는 해결 못 했던 문제
    : 부서별 최소급여 받는 사원 이름들 알고 싶다
  • (내생각) WHERE절에 그룹함수를 사용하고 싶을 때 서브쿼리를 이용한다고 생각해도 될 듯
SELECT last_name, job_id, salary
FROM employees
WHERE salary = ( SELECT MIN(salary)
		FROM employees)
  • (내생각) Q. 이거는 회사 최소급여 찾아서 (특정 값 하나) 최소급여 받는 사원 찾는 쿼리문 아닌가? '부서별'이 아니라?
    A. 문장이 오해돋게 쓰여진 듯.
    ['부서별 최소급여' 받는 사원 이름]이 아니라 [부서별 '최소급여 받는 사원' 이름]을 의도한 문제야
    즉, 부서별 이라기보다는 최소급여 받는 사원의 부서를 보겠다는 거


ㅇ HAVING절에서 서브쿼리 사용

  • HAVING절에서도 그룹함수(컬럼)+연산자+값 <- 이 부분이 서브쿼리
  • HAVING절에 들어있는 서브쿼리가 꼭 그룹함수를 사용할 필요는 없어

ㅇ 예제 : 50번 부서의 최저급여보다 최저급여가 많은 부서들을 찾아라.

SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) > ( SELECT MIN(salary)
			FROM employees
			WHERE department_id=50 )

ㅇ 단일 행 서브쿼리에서 NULL은?

ㅇ 실험) 이 명령문은 행을 반환할까?

  • 서브쿼리가 값을 하나도 찾지 못하면 연쇄적으로 메인쿼리도 값을 찾을 수 없게 돼
  • 즉, 서브쿼리에서 NULL 이 나오지 않도록 신경 써야 해
SELECT last_name, job_id
FROM employees
WHERE job_id = (SELECT job_id
		FROM employees
		WHERE last_name = 'Haas'

no rows selected

  • Haas라는 사원이 없어서 서브쿼리의 결과가 no row selected.
  • NULL값은 '='로 찾을 수 없어. (IS NULL 로 밖에 찾을 수 없어)
  • 그래서 메인쿼리 결과도 no row selected.

profile
STEP BY STEP

0개의 댓글