저자 : 아사이 아츠시
출판 : 한빛미디어
발매 : 2015.11.01
- 서브쿼리 : SELECT 명령에 의한 데이터 질의로, 상부가 아닌 하부의 부수적인 질의를 의미.
- SQL 명령문 안에 지정하는 하부 SELECT 명령으로 괄호로 묶어 지정. 특히 서브쿼리는 WHERE 구에서 주로 사용됨. WHERE 구는 SELECT, DELETE, UPDATE 구에서 사용할 수 있는데 이들 중 어떤 명령에서든 서브쿼리 사용 가능.
1. DELETE의 WHERE 구에서 서브쿼리 사용하기
1 2 3 | -- 최솟값을 가지는 행 삭제 (괄호로 서브쿼리를 지정해 삭제) DELETE FROM sample54 WHERE a = (SELECT MIN(a) FROM sample54); | cs |
- 단, MySQL에서는 위 쿼리를 실행할 수 없음.. (데이터를 추가하거나 갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없도록 되어 있기 때문)
에러를 발생하지 않고 실행하려면 다음과 같이 인라인 뷰로 임시 테이블을 만들도록 처리하면 됨.
1 2 3 | DELETE FROM sample54 WHERE a = (SELECT a FROM (SELECT MIN(a) AS a FROM sample54) AS x); | cs |
2. 스칼라 값
- SELECT 명령이 하나의 값만 반환하는 것을 '스칼라 값을 반환한다'고 함. 스칼라 값을 반환하는 SELECT 명령은 서브쿼리로써 사용하기 용이. 스칼라 값을 반환하는 서브쿼리를 특별히 스칼라 서브쿼리라 부르기도함.
- SELECT 구에서 하나의 열을 지정하고, GROUP BY를 지정하지 않은 채 집계함수를 사용하면 결과는 단일한 값이 됨.
(만약 GROUP BY로 그룹화를하면 몇 가지 그룹으로 나뉘어져 버릴 가능성이 있어 단일한 값이 반환되지 않을 수 있음)
또한, WHERE 조건으로 하나의 행만 검색하는 SELECT 명령도 스칼라값을 반환.
- =연산자(비교연산자)를 사용하여 비교할 경우엔 스칼라 값끼리 비교할 필요가 있다.
- 집계함수를 WHERE구에 사용할 수 없어서 HAVING 구를 사용했었는데,
스칼라 서브쿼라면 WHERE 구에 사용할 수 있으므로 집계함수를 사용해 집계한 결과를 조건식으로 사용할 수도 있다.
3. SELECT 구에서 서브쿼리 사용하기
- SELECT 구에서 서브쿼리를 지정할 때는 스칼라 서브쿼리가 필요.
1 2 3 4 | -- select 구에서 서브쿼리 사용하기 select (select COUNT(*) from sample51) as sq1, (select COUNT(*) from sample54) as sq2 | cs |
- MySQL 등에서는 위와 같이 FROM 구를 생략할 수 있지만 Oracle 등 전통적인 DB제품에서는 FROM 생략이 불가능해 FROM DUAL로 지정하여 실행. (DUAL은 시스템 쪽에서 데이터베이스에 기본으로 작성되는 테이블)
4. SET 구에서 서브쿼리 사용하기
- UPDATE의 SET구에서도 서브쿼리를 사용 가능.
ex) 모든 a열 값을 a열 값의 최대값으로 갱신.
1 2 3 4 5 6 | UPDATE sample54 SET a = (SELECT MAX(a) FROM sample54); -- mysql UPDATE sample54 SET a = (SELECT a FROM (SELECT MAX(a) AS a FROM sample54) AS x); | cs |
5. FROM 구에서 서브쿼리 사용하기
- SELECT 구나 SET구에서는 스칼라 서브쿼리를 지정해야 하지만 FROM 구에 기술할 경우에는 반드시 스칼라 값을 반환하지 않아도 됨.
1 | SELECT * FROM (SELECT * FROM sample54) sq; | cs |
- 위와 같은 구조를 '네스티드(nested) 구조', 또는 '중첩구조'나 '내포구조'라 부름.
- sq는 테이블 별명. FROM 구에서는 테이블이나 서브쿼리에 별명을 붙일 수 있는데,
테이블에는 이름이 붙여져 있지만 서브쿼리에는 이렇다 할 이름이 붙여져 있지 않음. 별명을 붙이는 것으로 비로소 서브쿼리의 이름을 지정. AS키워드를 사용해서 AS sq 로 지정해도 됨. (단, Oracle에서는 AS를 붙이지 않음)
- 중첩구조는 몇 단계로든 구성할 수 있음.
1 2 | -- 3단계 중첩 SELECT * FROM (SELECT * FROM (SELECT * FROM sample54) sq1) sq2; | cs |
- 실제 업무에서 FROM 구에 서브쿼리를 지정하여 사용하는 경우
Oracle에서는 LIMIT 구가 없음. ROWNUM으로 행 개수를 제한할 수 있지만, 정렬(ORDER BY) 후 상위 몇건을 추출하는 조건은 붙일 수 없음. ROWNUM의 경우 WHERE 구로 인해 번호가 할당되기 때문. 하지만 FROM 구에서 서브쿼리를 사용하는 것으로 Oracle에서도 정렬 후 상위 몇 건을 추출한다는 행 제한을 할 수 있음.
1 2 3 4 5 | -- Oracle에서 LIMIT 구의 대체 명령 SELECT * FROM ( SELECT * FROM sample54 ORDER BY a DESC ) sq WHERE ROWNUM <= 2; | cs |
6. INSERT 명령과 서브쿼리
INSERT 명령과 서브쿼리를 조합해 사용할 수도 있음.
1) VALUES 구의 일부로 서브쿼리를 사용
1 2 3 4 | INSERT INTO sample541 VALUES ( (SELECT COUNT(*) FROM sample51), (SELECT COUNT(*) FROM sample54) ); | cs |
1 2 3 | INSERT INTO sample541 SELECT 1,2; -- SELECT가 결과값으로 1과 2라는 상수를 반환하므로, -- INSERT INTO sample541 VALUES (1,2)와 같음 | cs |
1 | INSERT INTO sample542 SELECT * FROM sample543; | cs |
'Study > DB' 카테고리의 다른 글
[SQL 첫걸음] 6장.데이터베이스 객체 작성과 삭제 - 25.데이터베이스 객체 (0) | 2018.09.11 |
---|---|
[SQL 첫걸음] 5장.집계와 서브쿼리 - 24.상관 서브쿼리 (0) | 2018.09.10 |
[SQL 첫걸음] 5장.집계와 서브쿼리 - 22.그룹화(GROUP BY) (0) | 2018.09.04 |
[SQL 첫걸음] 5장.집계와 서브쿼리 - 21.COUNT 이외의 집계함수 (0) | 2018.08.31 |
[SQL 첫걸음] 5장.집계와 서브쿼리 - 20.행 갯수 구하기(COUNT) (0) | 2018.08.31 |