2022. 11. 3. 13:45ㆍ데이터베이스
서브 쿼리
- 단일 행 서브 쿼리
서브 쿼리란?
단일 열, 단일 행 서브 쿼리 :
- 서브 쿼리가 하나의 컬럼에서 하나의 행을 검색한다.
단일 열, 다중 행 서브 쿼리
- 서브 쿼리가 하나의 컬럼에서 여러 개의 행을 검색한다.
다중 열 서브 쿼리
- 서브 쿼리가 여러 개의 컬럼을 검색한다.
서브 쿼리는 WHERE절, HAVING절과 같이 조건 절에 주로 쓰이고 FROM절에 쓰이는 경우도 있다.
특히 FROM절에 쓰인 서브 쿼리는 인라인 뷰(Inline View)라고 부른다.
단일 행 서브 쿼리
SQL> SELECT [DISTINCT | ALL] 컬럼, 컬럼 ...
2 FROM 테이블
3 WHERE 컬럼 단일_행_연산자 (SELECT 문장 : Sub query문)
- 단일 행 연산자가 사용됨으로 반드시 서브 쿼리의 결과 값은 한 개만 검색돼야 한다.
- 단일 행 연산자 오른쪽에 기술한다.
(=, <, >, <=, >=, !=)
- WHERE절에 기술된 열의 숫자와 타입은 SELECT절과 1:1 대응 관계가 되어야 한다.
예제 1. 남궁연호보다 급여를 많이 받는 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름
2 FROM emp
3 WHERE sal > (SELECT sal
4 FROM emp
5 WHERE ename = '남궁연호');
사번 이름
---- ----------
0001 안영희
1001 문시현
1002 김주란
.............
.............
예제 2. 김선유보다 급여를 많이 받는 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름
2 FROM emp
3 WHERE sal > (SELECT sal
4 FROM emp
5 WHERE ename = '김선유');
WHERE sal > (SELECT sal
*
SELECT sal FROM emp WHERE ename = '김선유';
900
3200
SQL> select eno 사번, ename 이름
2 from emp
3 where sal > 900, 3200; -> sal은 단일 행 연산자이기 때문이다. 계산할려면 다중 행 연산자로 바꿔줘야한다.
3행에 오류:
ORA-01427: 단일 행 하위 질의에 2개 이상의 행이 리턴되었습니다.
**** 예측하기 힘든 단일 행 서브 쿼리를 수정하는 방법
① '=' 연산자는 'IN' 연산자로 바꾼다.
② 부등호 ('<', '>', '<=', '>=')는 any, all 연산자를 추가한다.
③ Max(), Min()과 같은 그룹 함수를 사용 한다.
예제 3. 문시현과 부서가 다르고 동일한 업무를 하는 사원의 정보를 검색한다.
SQL> SELECT eno 사번, ename 이름, dno 부서번호, job 업무
2 FROM emp
3 WHERE dno != (SELECT dno FROM emp WHERE ename = '문시현')
4 AND job = (SELECT job FROM emp WHERE ename = '문시현');
사번 이름 부서번호 업무
---- ---------- -------- -------
1002 김주란 20 모델링
1003 양선호 30 모델링
예제 4. 부산에서 근무하는 사원의 정보를 검색한다.
SQL> SELECT eno 사번, ename 이름
2 FROM emp
3 WHERE dno = (SELECT dno
4 FROM dept
5 WHERE loc = '부산');
사번 이름
---- ------
1002 김주란
2002 제갈민
3002 권아현
0120 김경현
SQL> SELECT eno 사번, ename 이름
2 FROM emp e, dept d
3 WHERE e.dno = d.dno
4 AND loc = '부산';
실습
1. 김혁윤 보다 평점이 우수한 학생의 학번과 이름을 검색한다.
SELECT SNO 학번, SNAME 이름, AVR 평점
2 FROM STUDENT
3 WHERE AVR > (SELECT AVR 평점 FROM STUDENT WHERE SNAME = '김혁윤');
2. 권현와 동일한 학년 학생 중에 평점이 강은혜와 동일한 학생을 검색한다.
SELECT SNO 학번, SNAME 이름, SYEAR 학년, AVR 평점
2 FROM STUDENT
3 WHERE SYEAR = (SELECT SYEAR FROM STUDENT WHERE SNAME = '권현')
4 AND AVR = (SELECT AVR FROM STUDENT WHERE SNAME = '강은혜');
3. 이학수학 과목과 동일한 학점수인 과목을 검색한다.
SELECT CNO 과목번호, CNAME 과목이름, ST_NUM 학점
2 FROM COURSE
3 WHERE ST_NUM = (SELECT ST_NUM FROM COURSE WHERE CNAME = '이산수학');
4. 타 학과에 송강 교수와 동일한 지위의 교수 명단을 검색한다.
SELECT PNO 교수번호, PNAME 교수이름, SECTION 담당학과, ORDERS 직위
2 FROM PROFESSOR
3 WHERE ORDERS = (SELECT ORDERS FROM PROFESSOR WHERE PNAME = '송강');
5. 제갈민의 입사일보다 나중에 부임한 교수의 명단을 검색한다.
SELECT PNO 교수번호, PNAME 교수이름, HIREDATE 부임일
2 FROM PROFESSOR, EMP
3 WHERE HIREDATE < (SELECT HDATE FROM EMP WHERE ENAME = '제갈민');
6. 강태용보다 일반 화학 과목의 학점(A,B,..)이 더 낮은 학생의 명단을 학점과 검색한다.
SELECT s.sno, sname, cname, grade
2 FROM student s, course c, score r, scgrade g
3 WHERE s.sno=r.sno AND r.cno=c.cno AND result BETWEEN loscore AND hiscore
4 AND cname='일반화학' AND grade > (SELECT grade FROM student s, course c, scgrade g,
5 score r WHERE s.sno=r.sno AND r.cno=c.cno AND result BETWEEN loscore AND hiscore
6 AND sname='강태용' AND cname='일반화학');
서브 쿼리 : 다중 행, 다중 열 서브 쿼리
다중 행 서브 쿼리
SQL> SELECT [DISTINCT | ALL] 컬럼, 컬럼 ...
2 FROM 테이블
3 WHERE 컬럼 다중_행_연산자 (SELECT 문장 : Sub query문)
- 다중 행 연산자
. IN : 나열된(검색된) 값 중에 하나만 일치하면 참이다.
. ANY : 나열된(검색된) 값 중에 조건에 맞는 것이 하나 이상 있으면 참이다.
. ALL : 모든 나열된(검색된) 값과 조건에 맞아야 한다.
EX)
sal in (1000,20000,200)
sal > any (100,200,300) 어떤것보다 작다. ----> 99
sal > all (100,200,300) 전체보다 작다. -------> 299
sal < any (100,200,300) 어떤것보다 크다. ---> 301
sal < all (100,200,300) 전체보다 크다. ----> 101
예제 1. 20번 부서원들과 동일한 관리자로부터 관리 받는 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름
2 FROM emp
3 WHERE mgr IN (SELECT mgr
4 FROM emp
5 WHERE dno = '20')
6 AND dno != '20';
사번 이름
---- ---------
1003 양선호
1001 문시현
2003 정의찬
2001 남궁연호
예제 2. 10번 부서원들보다 급여가 낮은 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름, dno 부서번호
2 FROM emp
3 WHERE sal < ALL (SELECT sal
4 FROM emp
5 WHERE dno = '10');
사번 이름 부서번호
---- ---------- --------
2008 윤고은 40
2007 이초록 30
2002 제갈민 20
0702 김민지 02
0309 김선유 02
SQL> SELECT eno 사번, ename 이름, dno 부서번호
2 FROM emp
3 WHERE sal < (SELECT MIN(sal) 4 FROM emp
5 WHERE dno = '10');
* 다중 행 연산자와 그룹함수
다중 행 연산자인 ALL이나 ANY는 다음과 같이 그룹 함수를 이용 표현할 수 있다.
그룹 함수는 [19장 그룹 함수]에서 자세히 설명한다.
* 컬럼 > ALL → 컬럼 > MAX() : 가장 큰 값보다 크다
* 컬럼 < ALL → 컬럼 < MIN() : 가장 작은 값보다 작다.
* 컬럼 > ANY → 컬럼 > MIN() : 가장 작은 값보다 크다.
* 컬럼 < ANY → 컬럼 < MAX() : 가장 큰 값보다 작다
다중 열 서브 쿼리
SQL> SELECT [DISTINCT | ALL] 컬럼, 컬럼 ...
2 FROM 테이블
3 WHERE (컬럼1, 컬럼2, ... ) IN (SELECT 문장 : Sub query문)
예제 3. 손하늘과 동일한 관리자의 관리를 받으면서 업무도 같은 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름, mgr 관리자, job 업무
2 FROM emp
3 WHERE (mgr, job) IN (SELECT mgr, job
4 FROM emp
5 WHERE ename = '손하늘')
6 AND ename != '손하늘';
사번 이름 관리 업무
---- ---------- ---- ----
0201 안영숙 0001 지원
손하늘이 두 명 이상이라면 수정이 불가능하다.
SQL> SELECT eno 사번, ename 이름, mgr 관리자, job 업무
2 FROM emp
3 WHERE mgr = (SELECT mgr FROM emp WHERE ename = '손하늘')
4 AND job = (SELECT job FROM emp WHERE ename = '손하늘')
5 AND ename != '손하늘';
예제 4. 김선유와 부서 및 업무가 동일한 사원을 검색한다.
SQL> SELECT eno 사번, ename 이름, dno 부서번호, job 업무
2 FROM emp
3 WHERE (dno, job) IN (SELECT dno, job
4 FROM emp
5 WHERE ename = '김선유')
6 AND ename != '김선유';
사번 이름 부서번호 업무
---- ---------- -------- -----
0702 김민지 02 회계
0302 박선경 02 회계
0301 이승철 02 회계
0269 권나현 10 분석
SQL> SELECT eno 사번, ename 이름, dno 부서번호, job 업무
2 FROM emp
3 WHERE dno in (SELECT dno FROM emp WHERE ename = '김선유')
4 AND job in (SELECT job FROM emp WHERE ename = '김선유')
5 AND ename != '김선유';
사번 이름 부서번호 업무
---- ---------- -------- -----
0801 천유정 02 분석
0301 이승철 02 회계
0302 박선경 02 회계
0702 김민지 02 회계
0269 권나현 10 분석
0401 김진성 10 회계
6 개의 행이 선택되었습니다.
SQL> SELECT ename, dno, job
2 FROM emp
3 WHERE ename = '김선유';
ENAME DN JOB
---------- -- --------
김선유 02 회계
김선유 10 분석
실습
1. 화학과 학생과 평점이 동일한 학생들을 검색한다.
SELECT SNO, SNAME, AVR, MAJOR
2 FROM STUDENT
3 WHERE AVR IN (SELECT AVR FROM STUDENT WHERE MAJOR = '화학')
4 AND MAJOR != '화학';
2. 화학과 교수와 부임일이 같은 직원을 검색한다.
SQL> SELECT ENO, ENAME, HDATE
2 FROM EMP
3 WHERE HDATE IN (SELECT HIREDATE FROM PROFESSOR WHERE SECTION = '화학');
3. 화학과 학생과 같은 학년에서 평점이 동일한 학생들을 검색한다.
SQL> SELECT SNO, SNAME, SYEAR, MAJOR, AVR
2 FROM STUDENT
3 WHERE AVR IN (SELECT AVR FROM STUDENT WHERE MAJOR = '화학')
4 AND SYEAR IN (SELECT SYEAR FROM STUDENT WHERE MAJOR = '화학')
5 AND MAJOR != '화학';
4. 10번 부서 사원들보다 년봉을 많이 받는 사원을 검색한다.
SQL> SELECT ENO, ENAME, SAL*12+NVL(COMM,0), DNO
2 FROM EMP
3 WHERE SAL*12+NVL(COMM,0) > ALL(SELECT SAL*12+NVL(COMM,0) FROM EMP WHERE DNO = '10')
4 AND DNO != '10';
5. 10번 부서 사원들과 업무와 성별이 동시에 일치하는 사원을 검색한다.
SQL> SELECT ENO, ENAME, JOB, SEX
2 FROM EMP
3 WHERE (JOB, SEX) IN (SELECT JOB, SEX FROM EMP WHERE DNO = '10')
4 AND DNO != '10';
집합연산자
*** 같은 데이터 유형이어야한다.
UNION
- 검색된 결과의 합으로 중복은 제거된다.
- 정렬을 유발 할수 있다.
UNION ALL
- 중복을 포함한 결과의 합을 검색한다.
- 그냥 다 띄움
INTERSECT
- 양쪽 모두에서 포함된 행을 검색한다.
MINUS
- 첫 번째 검색된 결과에서 두 번째 검색 결과를 제외한 나머지를 검색한다.
집합 연산
SQL> SELECT ...
2 [UNION ALL | UNION | INTERSECT | MINUS]
3 SELECT ...
예제 1. 2000년 이후에 입사한 사원과 부임한 교수의 명단을 검색한다.
SQL> SELECT pno 번호, pname 이름, hiredate 입사일_부임일
2 FROM professor
3 WHERE hiredate >= '2000/01/01'
4 UNION ALL
5 SELECT eno, ename, hdate
6 FROM emp
7 WHERE hdate >= '2000/01/01';
번호 이름 입사일_부
-------- ---------- ----------
1001 송강 2002/08/12
1006 장청아 2003/05/20
1007 이초아 2010/07/06
.............
.............
SQL> SELECT pno 번호, pname 이름, hiredate 입사일_부임일
2 FROM professor
3 WHERE hiredate > '2000/01/01'
4 UNION
5 SELECT eno, ename, hdate
6 FROM emp
7 WHERE hdate > '2000/01/01';
번호 이름 입사일_부
-------- ---------- ----------
0269 권나현 2015/05/21
0309 김선유 2011/01/03
0401 김진성 2008/03/13
.............
.............
예제 2. 제갈씨 성을 가진 사원 중에 지원 업무를 하지 않는 사원을 검색한다.
SQL> SELECT eno, ename, job
2 FROM emp
3 WHERE ename LIKE '제갈%'
4 MINUS
5 SELECT eno, ename, job
6 FROM emp
7 WHERE job = '지원';
ENO ENAME JOB
---- ---------- ----
2002 제갈민 개발
예제 3. 화학, 물리학과 학생들 중에 학점이 3.0 이상인 학생을 검색한다.
SQL> SELECT sno 학번, sname 이름, major 학과, avr 학점 FROM student
2 WHERE major IN ('화학','물리')
3 INTERSECT
4 SELECT sno, sname, major, avr FROM student 5 WHERE avr >= 3;
학번 이름 학과 학점
-------- ---------- ---------- ----------
905301 유태지 화학 3.28
914502 문수보 물리 3.33
914504 심빈경 물리 3.33
.............
.............
실습
1. 화학과 학생과 교수를 검색한다. (집합 연산자를 이용한다.)
SQL> SELECT SNO, SNAME, MAJOR
2 FROM STUDENT
3 WHERE MAJOR = '화학'
4 UNION
5 SELECT PNO, PNAME, SECTION
6 FROM PROFESSOR
7 WHERE SECTION = '화학';
2. 정교수의 명단과 모델링이 업무인 직원의 이름, 입사일(부임일)을 검색한다. - UNION사용
SELECT PNAME, ORDERS, HIREDATE
2 FROM PROFESSOR
3 WHERE ORDERS = '정교수'
4 UNION
5 SELECT ENAME, JOB, HDATE
6 FROM EMP
7 WHERE JOB = '모델링';
'데이터베이스' 카테고리의 다른 글
데이터베이스 - 트랜잭션 (0) | 2022.11.03 |
---|---|
데이터베이스 - DML 기초1 (0) | 2022.11.03 |
리눅스DB(사용자 계정 생성) (0) | 2022.11.03 |
오라클 DB 구조 (0) | 2022.11.03 |
오라클Q02 네트워크 설정 (0) | 2022.11.03 |