본문 바로가기
프로그래밍/데이터베이스

[SQL 기초 - 10장] 오라클 SQL 서브쿼리

by 잡학다방 2024. 12. 13.
반응형

안녕하세요!

오늘은 어제에 이어서 서브쿼리에 대해서 좀 더 알아보려고 합니다!

어제 내용을 잠깐 복습해보면,

서브쿼리의 분류는 세가지로 나눌 수 있었습니다.

1. 사용위치에 따른 분류

2. 반환하는 행, 컬럼의 개수에 따른 분류

3. 서브쿼리에서 메인 쿼리의 컬럼 사용 유무에 따른 분류

3번의 내용을 좀 보려고 하는데요, 어제 빠뜨린 내용이 있었습니다.

어제 제가 스칼라 서브쿼리를 얘기하면서 했던 내용을 기억하시나요?

서브쿼리 부분만 따로 블록지정해서 실행을 해보라고 했었죠.

이 때 실행이 되는 구문을 비상호연관 서브쿼리,

실행이 되지 않는 구문을 상호연관 서브쿼리 라고 합니다.

추가적으로 알아두시면 좋을것 같네요.

혹시 어제 내용이 기억나지 않는 분들은 아래 버튼을 눌러 복습하고 와주세요!

서브쿼리 문제

오늘은 문제를 풀면서 얘기를 해보겠습니다.

문제1

문제 1. emp 테이블에서 사원들의 급여 평균보다 높은 급여를 받는 직원을 조회하세요.

위와 같은 문제가 있다면 쿼리를 어떻게 작성 하실건가요?

먼저 사원들의 급여 평균을 구하고,

그 값보다 높은 급여를 받는 조건을 걸어서 조회를 하면 되지 않을까요?

1번 문제의 쿼리와 결과입니다.

먼저 서브쿼리를 보시면 AVG 함수를 통해서 sal 의 평균을 구하고,

메인 쿼리에서 WHERE 절에서 그 평균보다 sal 가 큰 값들로 한정시키고 있습니다.

어려우신 분들은 어제 SMITH 직원이 속한 부서의 직원을 조회하는 문제를 보세요!

문제2

그렇다면 다음 문제를 보도록 하겠습니다.

문제2. 사원이 속한 부서의 급여 평균보다 높은 급여를 받는 사원 정보를 조회하세요.

문제 이해가 되시나요?

쉽게 말하자면 SMITH 를 기준으로 본다면 SMITH 는 20번 부서입니다.

그 20번 부서에서는 5명이 있는데,

20번 부서에서 그 5명의 평균 sal 보다 많이 받는 사람을 조회하는 것입니다.

이것을 SMITH 로 한정하지 않고 모든 사원으로 범위를 확장하는 것이죠.

쿼리를 어떻게 작성하면 될까요?

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

위와 같이 작성해 주시면 되겠습니다!

이번 문제는 동일한 테이블에서 데이터롤 조회하기 때문에

한정자를 사용해야 합니다.

이렇게 작성하신 분들도 계실겁니다.

하지만 위의 쿼리는 서브쿼리 부분에서 emp.deptno 의 emp가

메인쿼리의 emp로 인식이 되기 때문에

서브쿼리의 결과는 모든 사원의 sal 평균이 되어서

결국 1번 문제와 같은 결과가 나오게 됩니다.

같은 이름의 테이블을 사용할 때는

한정자를 사용해서 구분해줘야 한다는 점 기억해주세요!

문제3

다음 문제입니다.

위와 같이 SMITH 와 WARD 가 속한 부서의 모든 사원 정보를 조회해보세요.

결과를 보시면 deptno 가 모두 20과 30 이죠?

어제 두 가지 결과가 나오는 서브쿼리와 메인쿼리를 연결 하려면

어떻게 작성해야 하는지 알려드렸습니다.

위 처럼 IN 연산자를 사용해야 한다고 했었죠.

= 연산자를 사용하면 쿼리를 해석했을 때

deptno = 20 OR 30

이렇게 되어서 틀린 구문이 된다고 했습니다.

따라서 IN 연산자를 사용해 서브쿼리의 복수개의 결과를 받아줘야 하는 것입니다.

그런데 여기서 한 가지 주의할 점이 있습니다.

서브쿼리의 결과가 복수개 이고, 만약 그 결과에 NULL 이 있을 때

NOT IN 연산자는 사용할 수 없습니다.

이 부분은 제가 지난번에도 설명 드렸던 부분입니다.

만약 WHERE mgr IN (7902, NULL);

이라는 절이 있다고 생각해보면

저 절을 해석하면 mgr = 7902 OR mgr = NULL 입니다.

mgr = NULL 이라는 구문은 올바르지 않은 부분이므로 false 가 나오겠지만

mgr = 7902 부분에서 맞는 값이 나온다면 OR 로 연결이 되어 있으므로

결과 조회가 가능합니다.

하지만 NOT IN 연산자는 어떻게 될까요?

mgr != 7902 AND mgr != NULL 로 해석 됩니다.

그런데 mgr != NULL 은 올바르지 않은 부분이므로 false 가 나오고

mgr != 7902 에서 만족하는 값이 나온다고 해도

AND로 엮여 있기 때문에 결과 조회가 불가능 합니다.

이 부분 꼭 기억해주세요!

 

서브쿼리를 사용할 때 한 행의 복수 컬럼도 조회할 수 있습니다.

위를 보시면 서브쿼리 부분에서 나오는 결과값은 위와 같습니다.

메인 쿼리를 보시면 WHERE 절에서 mgr과 deptno 가 한꺼번에 나왔습니다.

그렇게 되면 mgr = 7698 이고 deptno = 30 이거나

mgr = 7839 이고 deptno = 10

이라는 조건이 생기는 것이죠.

한 행의 복수 컬럼을 조회하는것을 pairwise 방식 이라고 합니다.

위의 쿼리는 non-pairwise 방식으로 작성한 쿼리 입니다.

얼핏보면 구문을 해석해봤을 때 위와 같은 결과가 나올 것이라 생각될 수도 있지만

mgr 과 deptno 를 한꺼번에 같이 보는것이 아니고 따로 보는 것이기 때문에

경우의 수가 4가지로 늘어나게 됩니다.

mgr deptno

7698 30

7698 10

7839 30

7839 10

결국 결과도 다르게 조회가 됩니다.

결과가 다르게 나오지 않도록

한 행의 컬럼 값을 하나씩 비교할지,

한 행의 복수 컬럼을 비교할지를

잘 선택해서 작성해야 합니다!!

오늘은 내용이 짧네요..

그래도 중요한 내용이니 복습 하면 분명 좋을 것입니다.

오늘도 끝까지 봐주셔서 감사합니다.

다음에 또 봐요~

 
반응형