Chapter 6: Combining SQL Queries
참조 : The Programmer's Guide to SQL
두 개 이상의 테이블의 데이터가 필요할 때 서브쿼리나 조인을 사용할 수 있다. 이번 챕터는 서브쿼리에 대해 공부한다.
서브쿼리에는 두종류가 있다.
- 독립적인 서브쿼리 non-correlated subquery : 포함된 쿼리가 한 번만 수행되며, 그 결과가 외부 쿼리에 전달된다.
- 연관된 서브쿼리 correlated : 외부 쿼리의 데이터를 필요로 하며, 외부 쿼리의 결과 레코드 마다 한 번씩 수행하게 된다.
성능은 당연히 독립적인 서브쿼리가 좋아보인다. 그렇다고 연관된 서브쿼리를 안 쓸 수도 없을테고 외부 쿼리Outter Query의 레코드 수를 줄이면 그나마 Inner Query 수행 횟수가 줄어 들테니 이 점을 유의해야겠다.
연관된 서브쿼리 예제1
SELECT CustomerID, CustomerName, (
SELECT COUNT(*) FROM CreditCards
WHERE CreditCards.CustomerID = Customers.CustomerID)
AS NumberOfCreditCards
FROM Customers
- 고객ID, 고객이름, 고객의 신용카드 거래 합계를 보여준다.
- Customers 테이블의 레코드 갯 수 만큼 서브 쿼리가 실행된다.
연관된 서브쿼리 예제2
SELECT e1.StudentID, e1.ClassID, (
SELECT COUNT(*) FROM Enrollment e2
WHERE e1.ClassID = e2.ClassID)—1
AS OtherStudentsInClass
FROM Enrollment e1
WHERE StudentID = 6;
- ID가 6인 학생이 등록한 수업에 참여하는 다른 학생들의 합계를 구한다.
- Enrollment 테이블에서 SudentID가 6인 레코드 갯수 만큼 서브쿼리를 수행한다.
독립적인 서브쿼리 예제 1
SELECT ExamID, SustainedOn FROM Exam
WHERE SustainedOn <= (
SELECT SustainedOn FROM Exam WHERE ExamID = 5)
ORDER BY SustainedOn DESC;
- 시험 ID가 5인 시험이 치뤄지기 이전에 치뤄진 모든 시험 목록을 역순으로 보여준다.
- 내부 쿼리는 한 번만 수행되고 그 결과를 외부 쿼리에서 사용한다.
독립적인 서브쿼리 예제 2
SELECT StudentID, Name FROM Student WHERE StudentID IN
(SELECT StudentID FROM Enrollment WHERE ClassID IN
(SELECT ClassID FROM Class WHERE ProfessorID IN
(SELECT ProfessorID FROM Professor
WHERE Name LIKE '%Williams%')));
- Williams 라는 이름이 들어가는 교수가 가르치는 학급에 등록한 학생들의 정보를 보여준다.
- 역시 전부 독립적인 서브쿼리로 여러개의 결과를 반환하기 때문에 IN을 사용했다.
EXISTS 연산자
- 외부 쿼리의 결과 레코드가 내부 쿼리 레코드 집합안에 포함되어 있다면, true.
- 따라서 연관된 쿼리로 작성해야 함.
- 따라서 a.커럼id = b.컬럼id 와 같은 공식이 내부 쿼리에 추가되어야 함.
- 그래야 외부 쿼리와 내부 쿼리가 연결 됨.
- 예제
SELECT StudentID, Name FROM Student s
WHERE EXISTS (
SELECT StudentID FROM StudentExam e
WHERE Mark < 40 AND e.StudentID = s.StudentID);
- Mark가 40점 이하인 학생 정보.
- AND e.StudentID = s.StudentID 없으면 그냥 Student 테이블의 모든 레코드 보여줌.
ALL 연산자
- 외부쿼리가 ALL 뒤에 있는 내부 쿼리의 결과를 모두 만족 시키는 경우 true.
-예제
SELECT StudentID, Grade FROM Enrollment e
WHERE Grade > ALL (
SELECT Mark FROM StudentExam s
WHERE s.StudentID = e.StudentID);
- 등록 정보 중에서 Grade가 그 학생이 치룬 모든 시험의 Mark보다 높은 학생 정보를 보여줌.
ANY 연산자
- 외부쿼리가 ANY 뒤에 있는 내부 쿼리의 결과에 하나라도 만족하는 경우 true.
- 예제
SELECT StudentID, Grade FROM Enrollment e
WHERE Grade < ANY (
SELECT Mark/2 FROM StudentExam s
WHERE s.StudentID = e.StudentID);
-등록 정보 중에서 Grade가 그 학생이 치룬 모든 시험의 Mark의 절반도 안되는 학생 정보를 보여줌.
쿼리 결과 데이터 조합하기
SELECT ColumnA, ColumnB FROM TableA
<Operator>
SELECT ColumnC, ColumnD FROM TableB;
Operator(오라클)
- UNION : 합집합
- UNION ALL : 합집합 + 교집합
- INTERSECT : 교집합
- MINUS : 차집합
흠.. EXISTS, ALL, ANY 어렵... -_-;;