✔️서브쿼리(Subquery)에 대해서 알아보자.
데이터 조회를 하다보면, 잦은 빈도로 서브쿼리를 사용하게 된다고 한다.
보통 서브쿼리는 실행 속도가 느려서 잘 안쓰는 것으로 막연하게 알고있어서 정리가 필요하다고 느꼈다.
✔️서브쿼리(Subquery)개념잡기
개념
-
서브쿼리는 하나의 SQL문 내에 괄호()로 감싸져서 표현되어 있는 또 다른 SQL문을 말한다.
-
서브쿼리를 포함하고 있는 쿼리를
외부쿼리(outer query)
라고 부르며, 서브쿼리는내부쿼리(inner query)
라고 부른다. -
SQL 내부에서 작성되는 일시적인 테이블인데, 여기서 '일시적인 테이블’이라는 부분이 성능적인 차이를 불러온다.
구분 | 설명 | 특징 |
---|---|---|
테이블(Table) | DB에 물리적으로 저장된 데이터(영속적) | 영속적 |
뷰(View) | 가상의 테이블, 접근할 때 마다 SELECT 구문이 실행됨 | 영속적, 물리적 저장 X |
서브쿼리(Subquery) | 가상의 테이블, SQL 구문 실행 중에만 존재 | 일시적, 물리적 저장 X |
- 세가지 모두 데이터를 저장하고 있는 테이블로써 활용한다는 공통점이 있다.
서브쿼리의 실행 순서
- 서브쿼리가 먼저 실행된 후 메인(부모) 쿼리가 실행된다.
- ORDER BY를 사용 할 수 없다.
-- 메인쿼리 영역 <- 서브쿼리가 실행된 후 실행
select *
from my_table
where target_id in (
-- (서브쿼리 영역 ) <- 먼저 실행
select id
from sub_table_noindex_51
where id < 50
)
- 서브쿼리는 하나의 SQL 문 안에 포함되어 있는 또 다른 SQL 문을 말한다.
- (select id from sub …) 같이 괄호()안에 있는 쿼리를 서브 쿼리라고 말한다.
Java의 상속과 비슷한 개념
- 서브쿼리는 메인쿼리의 컬럼을 사용할 수 있고, 메인쿼리는 서브쿼리의 컬럼을 사용할 수 없다.
- 상속당한 자식 객체는 부모 객체의 인스턴스를 사용할 수 있고, 부모는 자식객체의 인스턴스를 사용할 수 없다.
서브 쿼리의 장점을 알아보자.
- 쿼리를 구조화시키므로, 쿼리의 각 부분을 명확히 구분할 수 있게 해준다.
- 복잡한 JOIN이나 UNION과 같은 동작을 수행할 수 있는 또 다른 방법을 제공한다.
- 복잡한 JOIN이나 UNION 보다 좀 더 읽기 편해서 가독성이 좋다.
✔️서브쿼리 위치에 따른 명칭
- 서브쿼리는 위치에 따라 명칭이 다르다.
- 주관적으로 왜
탑 미들 바텀
같은 직관적이지 않은,스칼라 인라인
WHERE 절에 붙는일반 서브쿼리
라고 하는지 도통 이해가 안된다.
SELECT col1, (SELECT ...) -- 스칼라 서브쿼리(Scalar Sub Query)
FROM (SELECT ...) -- 인라인 뷰(Inline View)
WHERE col = (SELECT ...) -- 일반 서브쿼리
스칼라 서브쿼리(Scalar Sub Query)
- 스칼라(scalar) 는 ‘한번에 한가지만 처리하는’ 이라는 뜻을 가지고 있다.
- SELECT문 위치에 쓰이는 서브쿼리
- 이름 그대로 하나의 레코드만 리턴이 가능하며, 두개 이상의 레코드는 리턴할 수 없다.
- 다른 테이블에서 어떠한 값을 가져올 때 쓰인다.
- 일치하는 데이터가 없더라도 NULL값을 리턴할 수 있다. 이는 그룹함수의 특징중에 하나인데 스칼라 서브쿼리 또한 이러한 특징을 가지고 있다고 한다.
인라인 뷰(Inline View)
- 인라인 뷰는 별도의 객체 없이 직접 코드에 적었다라는 뜻을 가졌다고 한다.
- FROM문 위치에 쓰이는 서브쿼리
- 서브쿼리가 FROM절에 사용 될 경우 무조건 AS(별칭)을 지정해 주어야 한다.
중첩 서브쿼리(Nested Subquery)
- WHERE문 위치에 쓰이는 일반 서브쿼리
-- 조건값을 상수로 할 때
select name,height
from userTb
where heigjt > 178;
-- 조건값을 select로 특정할 때 (단 결과가 값이 하나여야됨)
select name, height
from userTb
where height > (select height from userTb where name in ('이름'));
-- 조건에 값이 여러개 들어올땐 any.
-- any는 in과 동일한 의미. or을 의미한다.
select name, height
from userTb
where height = any(select height from userTb where addr in ('주소'));
-- all은 도출된 모든 조건값에 대해 만족할 때. and를 의미
select *
from city
where population > all(select population from city where district = '뉴욕');
서브쿼리 사용 가능 한 곳
MySQL에서 서브쿼리를 포함할 수 있는 외부쿼리는 SELECT, INSERT, UPDATE, DELETE, SET, DO 문이 있다.
- SELECT
- FROM
- WHERE
- HAVING
- ORDER BY
- INSERT문의 VALUES 부분 대체제
- UPDATE문의 SET 부분 대체제
✔️서브쿼리 예제
회사원 정보 테이블
CREATE TABLE employee (
id INT AUTO_INCREMENT PRIMARY KEY,
이름 VARCHAR(),
연봉 INT,
직급 VARCHAR(64)
)
INSERT INTO employee VALUES(1,'허사장',20000000,'사장');
INSERT INTO
employee (이름,연봉,직급)
VALUES
('유부장',10000000,'부장'),
('박차장',5000000,'차장'),
('정과장',4000000,'과장'),
('정대리',3895000,'대리'),
('노사원',2500000,'사원'),
('하사원',2000000,'사원'),
('길인턴',1000000,'인턴');
스칼라 서브쿼리(Scalar Subquery)
-- 스칼라 서브쿼리(Scalar Subquery)
-- 정대리 급여와 테이블 전체 평균 급여를 구하시오.
SELECT 이름,연봉,(
SELECT ROUND(AVG(연봉),-1)
FROM employee) AS '평균급여'
FROM employee
WHERE 이름 = '정대리';
인라인 뷰 (Inline View)
-- 꼭 파생 테이블엔 as(별칭)을 정해줘야 한다.
SELECT * FROM(SELECT * FROM employee WHERE 직급 = '사원') --(X)
-- 직급이 사원인 사람들의 이름과 급여를 구하시오.
SELECT e.이름, e.연봉
FROM (
SELECT *
FROM employee AS 고용
WHERE 고용.직급 = '사원' e;
);
중첩 서브쿼리 - 단일 행
-- 정대리라는 사람의 직급을 구하시오.
SELECT 직급
FROM employee
WHERE 직급 = (SELECT 직급 FROM employee WHERE 이름 = '정대리');
중첩 서브쿼리 - 복수(다중) 행
- IN, ANY, ALL, EXISTS 등의 연산자로 얻은 서브쿼리 결과 여러개의 행을 반환.
-- 정대리보다 급여가 높은 사람들을 구하시오.
SELECT * FROM employee
WHERE 연봉 > ( SELECT 연봉 FROM employee WHERE 이름 = '정대리' )
-- 직급이 사원인 사람들을 구하시오.
SELECT * FROM employee
WHERE 직급 IN(
SELECT 직급
FROM employee
WHERE 직급 = '사원'
);
INSERT문 서브쿼리
-- 테이블 2의 정보를 뽑아서 그 데이터를 테이블 1에 넣어준다.
-- value()에 들어갈 자리를 서브쿼리로 대체 가능하다.
INSERT INTO table1 (SELECT * FROM table2)
DELETE문 서브쿼리
-- 인턴의 정보를 구해와서 삭제한다.
DELETE FROM employee
WHERE id = (SELECT id FROM employee where 직급 = '인턴');
UPDATE문 서브쿼리
-- 인턴에 정보를 구해와서 급여를 10만원 인상한다.
UPDATE employee SET 연봉=(연봉+10000)
WHERE id = (SELECT id FROM employee where 연봉 = '인턴')
✔️참고자료
서브쿼리 쓰기 싫어서 찾아본 블로그
서브 쿼리 정리
서브쿼리란 무엇인가
JPA에서 서브쿼리
스택오버플로우 Join vs Subquery
성능 관점에서의 서브쿼리
서브쿼리 총 정리
'CS > DB' 카테고리의 다른 글
SQL JOIN (0) | 2023.10.15 |
---|---|
트랜잭션에 대해 알아보자 (3) | 2023.09.15 |
DB, DBMS, SQL에 대해 알아보자 (0) | 2023.09.12 |