※ 부속질의(subquery) : 하나의 SQL 문 안에 다른 SQL 문이 중첩된 nested 질의를 말함
· 다른 테이블에서 가져온 데이터로 현재 테이블에 있는 정보를 찾거나 가공할 때 사용함
· 보통 데이터가 대량일 때 데이터를 모두 합쳐서 연산하는 조인보다 필요한 데이터만 찾아서 공급해주는 부속질의가 성능이 더 좋음
· 주질의(main query, 외부질의)와 부속질의(sub query, 내부질의)로 구성됨
1) 스칼라 부속질의 - SELECT 부속질의
· SELECT 절에서 사용되는 부속질의로, 부속질의의 결과 값을 단일 행, 단일 열의 스칼라 값으로 반환함
· 스칼라 부속질의는 원칙적으로 스칼라 값이 들어갈 수 있는 모든 곳에 사용 가능하며, 일반적으로 SELECT 문과 UPDATE SET 절에 사용됨
· 주질의와 부속질의와의 관계는 상관/비상관 모두 가능함
▶ 마당서점의 고객별 판매액을 보이시오(결과는 고객이름과 고객별 판매액을 출력)
SELECT (SELECT name FROM Customer cs WHERE cs.custid = os.custid) "name", SUM(saleprice) "total"
FROM Order od
GROUP BY od.custid;
▶ Orders 테이블에 각 주문에 맞는 도서이름을 입력하시오
UPDATE Orders
SET bookname = (SELECT bookname FROM Book WHERE Book.bookid = Orders.bookid);
2) 인라인 뷰 - FROM 부속질의
· FROM 절에서 사용되는 부속질의
· 테이블 이름 대신 인라인 뷰 부속질의를 사용하면 보통의 테이블과 같은 형태로 사용할 수 있음
· 부속질의 결과 반환되는 데이터는 다중 행, 다중 열이어도 상관 없음
· 다만 가상의 테이블인 뷰 형태로 제공되어 상관 부속질의로 사용될 수는 없음
▶ 고객번호가 2 이하인 고객의 판매액을 보이시오(결과는 고객이름과 고객별 판매액 출력)
SELECT cs.name, SUM(od.saleprice) "total"
FROM (SELECT custid, name FROM Customer WHERE custid <= 2) cs, Orders od
WHERE cs.custid = od.custid
GROUP BY cs.name;
☞ 곱집합 결과 : custid name ordered custid bookid saleprice orderdate
3) 중첩질의 - WHERE 부속질의 : WHERE 절에서 사용되는 부속질의
· WHERE 절은 보통 데이터를 선택하는 조건 혹은 술어(predicate)와 같이 사용됨. 그래서 중첩질의를 술어 부속질의(predicate subquery)라고도 함
① 비교 연산자 : 부속질의가 반드시 단일 행, 단일 열을 반환한다. 아닐 경우 질의를 처리할 수 없음
▶ 평균 주문 금액 이하의 주문에 대해서 주문번호와 금액을 보이시오
SELECT orderid, saleprice
FROM Orders
WHERE saleprice <= (SELECT AVG(saleprice) FROM Orders);
▶ 각 고객의 평균 주문 금액보다 큰 금액의 주문 내역에 대해서 주문번호, 고객번호, 금액을 보이시오
SELECT orderid, custid, saleprice
FROM Orders od
WHERE saleprice > (SELCET AVG(saleprice) FROM Orders so WHERE od.custid = so.custid);
② IN, NOT IN
⑴ IN 연산자 : 주질의 속성 값이 부속질의에서 제공한 결과 집합에 있는지 확인(check)하는 역할을 함. IN 연산자는 부속질의의 결과 다중 행을 가질 수 있음
· 주질의는 WHERE 절에 사용되는 속성값을 부속질의의 결과 집합과 비교해 하나라도 있으면 참이 된다
⑵ NOT IN은 이와 반대로 값이 존재하지 않으면 참이 된다
▶ 대한민국에 거주하는 고객에게 판매한 도서의 총 판매액을 구하시오
SELECT SUM(saleprice) "total"
FROM Orders
WHRER custid IN(SELECT custid FROM Customer WHERE address LIKE '%대한민국%');
③ ALL, SOME(ANY) : ALL은 모두, SOME(ANY)은 어떠한(최소한 하나라도)이라는 의미를 가짐
· 구문 구조
scalar_expression {비교연산자(= or < > or != or > or >= or !> or < or <= or <!)}
{ALL or SOME or ANY} (부속질의)
▶ 3번 고객이 주문한 도서의 최고 금액보다 더 비싼 도서를 구입한 주문의 주문번호와 금액을 보이시오
SELECT orderid, saleprice
FROM Orders
WHERE saleprice > ALL(SELECT saleprice FROM Orders WHERE custid = '3');
④ EXISTS, NOT EXISTS : 데이터의 유무를 확인하는 연산자
· 주질의에서 부속질의로 제공된 속성의 값을 가지고 부속질의에 조건을 만족하여 값이 존재하면 참이 되고, 주질의는 해당 행의 데이터를 출력함
· NOT EXIST의 경우 이와 반대로 동작함
· 구문 구조
WHERE [NOT] EXISTS (부속질의)
▶ EXISTS 연산자로 대한민국에 거주하는 고객에게 판매한 도서의 총 판매액을 구하시오
SELECT SUM(saleprice) "total"
FROM Order od
WHERE EXISTS (SELECT * FROM Customer cs WHERE address LIKE '%대한민국%' AND cs.custid = od.custid);