[ 서브 쿼리 목차 ]
1. 서브 쿼리의 기본 개념
2. 단일행 서브 쿼리
3. 다중행 서브 쿼리
1) IN 연산자
2) ALL 연산자
3) ANY 연산자
4) EXISTS 연산자
[ 1 ] 서브 쿼리의 기본 개념
- 서브 쿼리
: 하나의 SELECT 문장의 절 안에 포함된 또 하나의 SELECT 문장이다.
- 서브 쿼리를 포함하고 있는 쿼리문을 메인 쿼리,
포함된 또 하나의 쿼리를 서브 쿼리라고 한다.
- 서브 쿼리는 비교 연산자의 오른쪽에 기술해야 하고,
반드시 괄호로 둘러쌓여야 한다.
- 서브 쿼리는 메인 쿼리가 실행되기 이전에 한번만 실행된다.
* 서브 쿼리 : 쿼리문 안에 새로운 쿼리가 들어있는 것
ex) 아래의 그림을 보면, ENAME이 'SCOTT'인 DEPTNO을 골라서 DEPTNO과
같은지를 본다. (WHERE절)
-- 08. 서브쿼리 : 조인으로 한 것을 서브쿼리로 바꿔서 적을 수 있다.
SELECT DNAME
FROM DEPT
WHERE DEPTNO = (SELECT DEPTNO
FROM EMP
WHERE ENAME='SCOTT');
-- 위의 코드를 JOIN 조인으로 한 방법
SELECT DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND EMP.ENAME='SCOTT';
[ 2 ] 단일행 서브 쿼리
- 단일 행(Single Row) 서브 쿼리
: 수행 결과가 오직 하나의 로우(행, row)만을 반환하는 서브 쿼리를 갖는 것
- 단일 행 서브 쿼리문에서는 이렇게 오직 하나의 로우(행, row)로 반환되는
서브 쿼리의 결과는 메인 쿼리에 보내게 되는데
메인 쿼리의 WHERE 절에서는 단일 행 비교 연산자인 =, >, >=, <, <=, <> 를
사용해야 한다.
* 단일행 서브 쿼리는 비교 연산자를 사용해서 비교 할 수 있다.
SELECT ENAME, SAL
FROM EMP
WHERE SAL > ( SELECT AVG(SAL)
FROM EMP);
-- 아래 쉅 내용 코드 --
-- 단일행 서브 쿼리 : 비교연산자 사용 가능
SELECT ENAME, SAL
FROM EMP
WHERE SAL > ( SELECT AVG(SAL) FROM EMP);
SELECT AVG(SAL) FROM EMP;
[ 3 ] 다중행 서브 쿼리
- 다중 행 서브 쿼리
: 서브 쿼리에서 반환되는 결과가 하나 이상의 행일때 사용하는 서브 쿼리
- 다중 행 서브 쿼리는 반드시 다중 행 연산자(Multiple Row Operator)와 함께
사용해야 한다.
* 다중행 서브 쿼리는 비교연산자 사용 불가
종류 | 의미 |
IN | 메인 쿼리의 비교 조건(' = ' 연산자로 비교할 경우)이 서브 쿼리의 결과 중에서 하나라도 일치하면 참이다. |
ANY, SOME | 메인 쿼리의 비교 조건이 서브 쿼리의 검색 결과와 하나 이상이 일치하면 참이다. |
ALL | 메인 쿼리의 비교 조건이 서브 쿼리의 검색 결과와 모든 값이 일치하면 참이다. |
EXIST | 메인 쿼리의 비교 조건이 서브 쿼리의 결과 중에서 만족하는 값이 하나라도 존재하면 참이다. |
1. IN 연산자
- IN 연산자
: 메인 쿼리의 비교 조건에서 서브 쿼리의 출력 결과와 하나라도 일치하면
메인 쿼리의 WHERE 절이 참이 되는 연산자
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE DEPTNO IN ( SELECT DISTINCT DEPTNO
FROM EMP
WHERE SAL>=3000);
-- 아래 쉅 내용 코드 --
--IN 연산자 : 서브 쿼리의 결과 중 하나라도 일치하면 메인 쿼리의 WHERE 절은 참이 된다.
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE DEPTNO IN ( SELECT DISTINCT DEPTNO
FROM EMP
WHERE SAL >= 3000);
-- DEPTNO =10 일때랑 DEPTNO=20일때 두 경우 해당하는 것 다 출력
SELECT DISTINCT DEPTNO
FROM EMP
WHERE SAL >= 3000;
-- DEPTNO = 10, 20 두개 출력
2. ALL 연산자
- ALL 조건
: 메인 쿼리의 비교 조건이 서브 쿼리의 검색 결과와
모든 값이 일치하면 참이다.
-- 아래 쉅 내용 코드 --
-- ALL 연산자 : 메인 쿼리의 비교 조건이 서브 쿼리의 검색 결과와 모든 값이 일치하면 참
SELECT ENAME, SAL
FROM EMP
WHERE SAL > ALL ( SELECT SAL
FROM EMP
WHERE DEPTNO = 30);
-- 서브 쿼리의 출력 결과의 모든것을 다 만족해서 그 모든것들 보다 큰 SAL을 찾는게 WHERE절
-- 서브 쿼리 검색한 결과 가장 큰 값은 2850이다. 그러니깐 WHERE절은 2850보다 큰 SAL인 조건이 된다.
SELECT SAL
FROM EMP
WHERE DEPTNO = 30;
-- 6개의 SAL 값 출력 ( 그중 가장 큰 SAL 값은 2850, 가장 작은 SAL 값은 950 이다.)
3. ANY 연산자
- ANY 조건
: 메인 쿼리의 비교 조건이 서브 쿼리의 검색 결과와
하나 이상만 일치하면 참이다.
-- 아래 쉅 내용 코드 --
-- ANY 연산자 : 서브 쿼리의 검색 결과와 하나만 이라도 일치하면 메인 쿼리의 WHERE절은 참
SELECT ENAME, SAL
FROM EMP
WHERE SAL > ANY ( SELECT SAL
FROM EMP
WHERE DEPTNO = 30);
-- 서브 쿼리의 결과 중 가장 작은 SAL값인 950 보다만 메인 쿼리의 SAL 값이 크면 하나 이상 다
-- 만족하게 되면 WHERE 절은 참이 된다.
4. EXISTS 연산자
- 서브 쿼리에 결과 값이 하나 이상 존재하면 조건식이 모두 true,
존재하지 않으면 모두 false 가 되는 연산자이다.
-- 아래 쉅 내용 코드 --
-- EXISTS 연산자 : 서브 쿼리의 결과값이 하나만이라도 존재한다면
-- 메인 쿼리의 조건식은 모두 TRUE, 존재하지 않으면 조건식은 FALSE
SELECT *
FROM EMP
WHERE 1=1;
-- 1=1 은 무조건 참이다. -> WHERE 조건절 참이니 모든 컬럼 다 출력됨
SELECT *
FROM EMP
WHERE EXISTS ( SELECT DNAME
FROM DEPT
WHERE DEPTNO=10 );
-- SELECT DNAME FROM DEPT WHERE DEPTNO=10 의 값이 ACCOUNTING 으로 하나 존재한다.
-- 따라서 서브 쿼리의 결과 값이 ACCOUNTING 으로 하나 존재하므로 메인 쿼리는 출력 된다.
SELECT *
FROM EMP
WHERE EXISTS ( SELECT DNAME
FROM DEPT
WHERE DEPTNO=60 );
-- SELECT DNAME FROM DEPT WHERE DEPTNO=60 의 값은 하나도 존재하지 않는다.
-- 따라서 서브 쿼리의 결과값이 하나도 존재하지 않아 WHERE절 조건식은 FALSE가 되어
-- 메인 쿼리는 아무것도 출력이 안된다.
CONN MADANG/MADANG
SELECT NAME, ADDRESS
FROM CUSTOMER CS
WHERE EXISTS (SELECT * FROM ORDERS OD WHERE CS.CUSTID=OD.CUSTID);
-- EXISTS 연산자를 사용하여 대한민국에 거주하는 고객에게 판매한 도서의 총 판매액을 구하기
SELECT SUM(SALEPRICE) "TOTAL"
FROM ORDERS OD
WHERE EXISTS (
SELECT *
FROM CUSTOMER CS
WHERE ADDRESS LIKE '%대한민국%' AND CS.CUSTID=OD.CUSTID
);
[ 과제문제 08-02-2번 문제 ]
Q2. IN연산자를 이용하여 부서별로 가장 많은 급여를 받는 사원의 정보
(사원번호,사원명,급여,부 서번호)를 출력하는 SQL문을 작성 하세요.
A2.
'DataBase' 카테고리의 다른 글
10_ DML (0) | 2022.12.15 |
---|---|
09_DDL (1) | 2022.12.15 |
07_조인 (0) | 2022.12.14 |
06_그룹 쿼리와 집합 연산자 (2) | 2022.12.14 |
05_SQL 주요 함수 (0) | 2022.12.13 |