서브 쿼리
- 하나의 SQL문 안에 포함되어 있는 또 다른 SQL.
- 서브 쿼리는 알려지지 ㅇ낳은 기준을 이용한 검색을 위해 사용한다.
- 서브 쿼리는 메인쿼리가 서브쿼리를 포함하는 종속적인 관계이다.
서브쿼리 사용 시 주의사항
- 서브 쿼리를 괄호로 감싸서 사용한다.
- 서브 쿼리는 단일 행(Single Row) 또는 복수 행(Multiple Row) 비교 연산자와 함께 사용 가능하다. 단일 행 비교 연산자는 서브 쿼리의 결과가 반드시 1건 이하이어야 하고 복수 행 비교 연산자는 서브쿼리의 결과 건수와 상관없다.
- 서브 쿼리에서는 ORDER BY를 사용하지 못한다. ORDER BY절은 SELECT절에서 오직 한 개만 올 수 있기 때문에 ORDER BY절은 메인쿼리의 마지막 문장에 위치해야 한다.
1. 단일행 서브쿼리
- 서브 쿼리의 실행 결과가 항상 1건 이해인 서브 쿼리를 의미한다.
- 단일행 서브 쿼리는 단일 행 비교 연산자와 함께 사용된다.
- 단일 행 비교 연산자는 =, <, <=, >=, <>이 있다.
[예제] 정남일 선수의 소속팀을 알아내는 SQL문(서브 쿼리 부분)과 이 결과를 이용해서 해당 팀에 소속된 선수들의 정보를 출력하는 SQL문(메인쿼리 부분)으로 구성된다. 정남일 선수가 소속된 팀의 선수들에 대한 정보를 표시하는 문제를 서브쿼리 방식의 SQL문으로 작성하면 다음과 같다.
1
2
3
4
5
6
|
SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
WHERE TEAM_ID = (SELECT TEAM_ID
FROM PLAYER
WHERE PLAYER_NAME = '정남일')
ORDER BY PLAYER_NAME;
|
cs |
[예제] 선수들의 평균 키를 알아내어 평균 키보다 작거나 같은 선수들을 출력
1
2
3
4
5
|
SELECT PLAYER_NAME 선수명, POSITION 표지션, BACK_NO 백넘버
FROM PLAYER
WHERE HEIGHT <= (SELECT AVG(HEIGHT)
FROM PLAYER)
ORDER BY PLAYER_NAME;
|
cs |
2. 다중행 서브 쿼리
- 서브 쿼리의 실행 결과가 여러 건인 서브 쿼리를 의미한다.
- 다중행 서브 쿼리는 다중행 비교 연산자와 함께 사용된다.
- 다중행 비교 연산자에는 IN, ALL, ANY, SOME, EXISTS가 있다. 그렇지 않으면 SQL문은 오류를 반환한다.
[예제] 선수들 중에서 ‘정현수’라는 선수가 소속되어 있는 팀 정보를 출력
1
2
3
4
5
6
|
SELECT REGION_NAME 연고지명, TEAM_NAME 팀명, E_TEAM_NAME 영문팀명
FROM TEAM
WHERE TEAM_ID IN (SELECT TEAM_ID
FROM PLAYER
WHERE PLAYER_NAME = '정현수')
ORDER BY TEAM_NAME;
|
cs |
3. 다중 칼럼 서브 쿼리
- 서브 쿼리의 실행결과로 여러 칼럼을 반환한다.
- 메인 쿼리의 조건절에 여러 칼럼을 동시에 비교할 수 있다.
- 서브 쿼리와 메인 쿼리에서 비교하고자 하는 칼럼 개수와 컬럼의 위치가 동일해야 한다.
- 다중 컬럼 서브 쿼리는 서브 쿼리의 결과로 여러 개의 칼럼의 반환되어 메인 쿼리의 조건과 동일시에 비교되는 것을 의미한다.
[예제] 소속팀별 키가 가장 작은 사람들의 정보를 출력
1
2
3
4
5
6
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE (TEAM_ID, HEIGHT) IN (SELECT TEAM_ID, MIN(HEIGHT)
FROM PLAYER GROUP
BY TEAM_ID)
ORDER BY TEAM_ID, PLAYER_NAME;
|
cs |
조인(Join)
- 둘 이상의 테이블을 연결하여 데이터를 검색하는 방법이다.
- 보통 둘 이상의 행들의 공통된 값 Primary Key 및 Foreign Key 값을 사용하여 조인한다.
- 두 개의 테이블을 SELECT문장 안에서 조인하려면 적어도 하나의 칼럼이 그 두 테이블 사이에서 공유되어야 한다.
1.Inner Join
- 가장 일반적인 형태의 조인을 내부 조인(Inner Join)이라고 한다.
- 서로 매칭 되는 것만 엮어 조회한다. 즉 두 개의 집합 (A, B)의 교집합이라고 이해하면 된다.
- 테이블 간의 공통 칼럼을 사용하여 칼럼 값이 같은 데이터들을 연결한 조인 방법을 말한다.
[그림 Ⅱ-1-12]는 선수와 팀, 팀과 운동장 테이블 간의 관계를 설명한 것이다.
[예제] 세 개의 테이블에 대한 JOIN을 구현해 보도록 한다. 선수들 별로 홈그라운드 경기장이 어디인지를 출력하고 싶다고 했을 때, 선수 테이블과 운동장 테이블이 서로 관계가 없으므로 중간에 팀 테이블이라는 서로 연관관계가 있는 테이블을 추가해서 세 개의 테이블을 JOIN 해야만 원하는 데이터를 얻을 수 있다.
// INNER JOIN은 INNER 키워드를 생략 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션,
T.REGION_NAME 연고지, T.TEAM_NAME 팀명,
S.STADIUM_NAME 구장명
FROM PLAYER P, TEAM T, STADIUM S
WHERE P.TEAM_ID = T.TEAM_ID
AND T.STADIUM_ID = S.STADIUM_ID
ORDER BY 선수명;
//또는 INNER JOIN을 명시하여 사용할 수도 있다.
SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션,
T.REGION_NAME 연고지, T.TEAM_NAME 팀명,
S.STADIUM_NAME 구장명
FROM PLAYER P INNER JOIN TEAM T
ON P.TEAM_ID = T.TEAM_ID
INNER JOIN STADIUM S
ON T.STADIUM_ID = S.STADIUM_ID
ORDER BY 선수명;
|
cs |
2. Outer Join
- 매칭뿐만 아니라 미매칭 데이터도 함께 조회한다.
- 동일 조건에서 조인 조건을 만족하는 값이 없는 행들을 조회하기 위해 외부(Outer Join)를 사용한다.
- Outer Join 연산자는 "(+)"이다.
- 조인 시 값이 없는 조인 측에 "(+)"를 위치시킨다.
- Outer Join 연산자는 표현식의 한 편에만 올 수 있다.
[예제] 부서 번호를 조회하는 예제
1
2
3
|
SELECT DISTINCT(e.deptno), d.deptno
FROM emp e, dept d
WHERE e.deptno(+) = d.deptno;
|
cs |
[결과] DEPTNO DEPTNO
------- --------
10 10
20 20
30 30
40
Outer Join을 사용하는 테이블에 추가로 조건절이 있다면 (+) 연산자를 모두 해야 한다.
// ename LIKE 조건절에 (+) 연산자가 누락된 경우
1
2
3
4
|
SELECT DISTINCT(a.deptno), b.deptno
FROM emp a, dept b
WHERE a.deptno(+) = b.deptno
AND a.ename LIKE '%';
|
cs |
[결과] DEPTNO DEPTNO
---------- ----------
10 10
20 20
30 30
// ename LIKE 조건절에 (+) 연산자를 추가해야 정상적으로 데이터가 조회된다.
1
2
3
4
|
SELECT DISTINCT(a.deptno), b.deptno
FROM emp a, dept b
WHERE a.deptno(+) = b.deptno
AND a.ename(+) LIKE '%';
|
cs |
[결과] DEPTNO DEPTNO
------- --------
10 10
20 20
30 30
40
'개발자였던 것 > 데이터베이스' 카테고리의 다른 글
[Oracle] LPAD와 RPAD (0) | 2020.12.02 |
---|---|
[Oracle] subSTR와 subSTRB (0) | 2020.12.02 |
[Oracle] CASE와 DECODE문 (0) | 2020.12.02 |
SQL developer ORA-01045 오류 (0) | 2020.09.06 |
SQL developer 계정 생성/권한부여/수정/삭제 (0) | 2020.09.06 |