서브쿼리

유석현(SeokHyun Yu)·2022년 8월 12일
0

SQL

목록 보기
23/45
post-thumbnail

서론

서브쿼리는 SQL 명령문 안에 지정하는 하부 SELECT 명령으로 괄호로 묶어 지정한다.

지금부터 다양한 명령이나 구에서 사용하는 예를 들어가며 사용법에 관해 자세히 알아보겠다.


1. DELETE의 WHERE 구에서 서브쿼리 사용하기

먼저 DELETE 명령의 WHERE 구에서 서브쿼리를 사용하는 예를 살펴보겠다.

위 테이블에서 a 열의 값이 가장 작은 행을 삭제하려 한다.

이 테이블에는 네 개의 행밖에 없으므로 a가 20인 행이 가장 작다는 것을 한눈에 알아볼 수 있다.

따라서 간단하게 DELETE FROM sample_table WHERE a=20; 이라는 DELETE 명령을 실행해 a 열의 값이 가장 작은 행을 삭제할 수 있다.

하지만 실제 데이터베이스에 데이터가 이렇게 적은 경우는 없다.

수십, 수백, 수천만개의 데이터가 쌓여있는 테이블에서 가장 작은 행이 어느 것인지 전혀 파악할 수 없는 경우에는 어떻게 해야 할까?

아마 먼저 SELECT 명령으로 검색하고자 할 것이다.

SELECT MIN(a) FROM sample_table;

MIN 집계함수를 통해 a 열의 최솟값이 20인 것을 알았다.

이 SELECT 명령을 DELETE 명령의 WHERE 구에서 사용하면 하나의 DELETE 명령으로 원하는 행을 삭제할 수 있다.

DELETE 명령과 SELECT 명령을 결합시켜 버리는 것이다.

DELETE FROM sample_table WHERE a=(SELECT MIN(a) FROM sample_table);

단, MySQL에서는 위의 쿼리를 실행하면 에러가 발생한다.

데이터를 추가하거나 갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없도록 되어 있기 때문이다.

에러를 발생시키지 않고 실행하려면 다음과 같이 인라인 뷰로 임시 테이블을 만들도록 처리하면 된다.

DELETE FROM sample_table
WHERE a=(
	SELECT * FROM (
    	SELECT MIN(a) FROM sample_table;
    ) AS temp
);

한편 SQL에는 변수를 사용할 수 있다.

구현방법에는 여러 가지가 있으므로 자세하게 설명할 수는 없지만 변수를 사용할 수 있다는 것은 알아두기를 바란다.

다음은 MySQL에서의 변수 설정 방법과 사용 예시이다.

set @min = (SELECT MIN(a) FROM sample_table);

DELETE FROM sample_table WHERE a=@min;

2. 스칼라 값

서브쿼리를 사용할 때는 그 SELECT 명령이 어떤 값을 반환하는지 주의할 필요가 있다.

여러 가지 패턴 중에서도 다음과 같은 네 가지가 일반적인 서브쿼리 반환 패턴이다.


1. 하나의 값을 반환하는 패턴

SELECT MIN(a) FROM sample_table;



2. 복수의 행이 반환되지만 열은 하나인 패턴

SELECT id FROM sample_table;



3. 하나의 행이 반환되지만 열이 복수인 패턴

SELECT MIN(id), MAX(a) FROM sample_table;



4. 복수의 행, 복수의 열이 반환되는 패턴

SELECT id, a FROM sample_table;



이때 패턴 1만 다른 패턴과 달리 하나의 값을 반환한다.

이렇게 반환된 하나의 값을 '단일 값' 또는 '스칼라 값'이라 부른다.

스칼라 값을 반환하는 SELECT 명령을 특별 취급하는 이유는 서브쿼리로서 사용하기 쉽기 때문이다.

이처럼 스칼라 값을 반환하도록 SELECT 명령을 작성하고자 한다면 SELECT 구에서 단일 열을 지정해야 한다.

복수 열을 반환하도록 하면 패턴 3이나 4가 되버리기 때문이다.

스칼라 값을 반환하는 서브쿼리를 특별히 '스칼라 서브쿼리'라 부르기도 한다.


3. SELECT 구에서 서브쿼리 사용하기

앞서 언급한 예에서는 WHERE 구에 서브쿼리를 사용했다.

그 밖에도 서브쿼리는 SELECT 구, UPDATE의 SET 구 등 다양한 구 안에서 지정할 수 있다.

SELECT
	(SELECT COUNT(*) FROM sample_table) AS sq1;

여기서 한 가지 주의할 점이 있는데 서브쿼리가 아닌 상부의 SELECT 명령에는 FROM 구가 없다는 것이다.

MySQL 등에서는 실제로 FROM 구를 생략할 수 있다.

하지만 Oracle 등 전통적인 데이터베이스 제품에서는 FROM 을 생략할 수 없다.

이때 Oracle에서는 다음과 같이 FROM DUAL로 지정하면 실행할 수 있다.

DUAL은 시스템 쪽에서 데이터베이스에 기본으로 작성되는 테이블이다.

SELECT
	(SELECT COUNT(*) FROM sample_table) AS sq1
FROM DUAL;

4. SET 구에서 서브쿼리 사용하기

UPDATE sample_table SET a=(SELECT MAX(a) FROM sample_table);

실제로 UPDATE의 SET 구에서 서브쿼리가 많이 쓰이진 않는다.

이런 명령도 가능하다 라는 것을 보여주는 예제이다.


5. FROM 구에서 서브쿼리 사용하기

FROM 구에서도 서브쿼리를 사용할 수 있다.

SELECT * FROM (SELECT * FROM sample_table) AS st;

FROM 구에서 서브쿼리를 사용할 때는 별명(alias)을 꼭 붙여주어야 한다.

테이블에는 이름이 붙여져 있지만 서브쿼리에는 이렇다 할 이름이 붙여져 있지 않기 때문이다.


6. INSERT 명령과 서브쿼리

INSERT INTO sample_table(count) VALUES(
	(SELECT COUNT(*) FROM sample_table)
);

INSERT 명령도 서브쿼리를 조합해 사용할 수 있다.

profile
Backend Engineer

0개의 댓글