개요
- SQL의 서브쿼리에 대해 이해하고, 예제를 통해 파악해 봅시다.
서브쿼리란?
- SQL문법은 기본적으로 SELECT, FROM, WHERE 이다.
- 서브쿼리란 위치에 따라 SELECT, FROM ,WHERE절로 나뉜다.
- SELECT절에 [SELECT, FROM, WHERE]를 넣는다.
- FROM절에 [SELECT, FROM, WHERE]를 넣는다.
- WHERE절에 [SELECT, FROM, WHERE]를 넣는다.
- 가장 일반적인 것은 WHERE 절이며, 실무에선 FROM절과 WHERE절을 가장 많이 사용한다.
- 예제와 함께 사용해봅시다.
현재 나의 테이블 상황

각 절의 서브쿼리
SELECT
- 하나의 열처럼 사용된다.
- 따라서, 단일 값을 반환해야합니다.
- 질문
- 두 테이블간 공통값을 매칭하고, A테이블의 칼럼은 전부 나오게하고, B테이블의 칼럼은 하나만 나오게 해라.
- 위 질문의 서브쿼리가 아닌, JOIN을 사용하면 아래와같이 표시될 수 있다.
select d.*,e.name from Department d join Employee e on d.department_id = e.department_id;

- 위 쿼리를, 서브쿼리 형식으로 바꾸면 아래와 같다.
select *, (select name from Employee e where d.department_id = e.department_id) from Department d;

- 하지만, select절에 사용되는 서브쿼리의 경우 단일값만 반환 가능하기 떄문에 에러가 나는 모습이다.
- 후술하겠지만, from 또는 where절에는 반환값이 여러개 일 수 있기 때문에 아래와같은 쿼리로 수정되야한다.
select d.*,e.name from Department d, (select * from Employee) as e where e.department_id = e.department_id;

FROM
- 하나의 테이블 처럼 사용된다
- 테이블 처럼 사용되므로, 열 이름과 테이블 명을 꼭 as를 통해 별칭을 지정해줘야 한다.
- 질문
- A테이블의 모든 칼럼을 표기하고, B테이블은 하기의 설명을 따른다.
- B테이블의 deparment_id별로 salary를 계산하고, 그 숫자가 75000이상인 데이터들만 표기하시오.
- 위 질문의 서브쿼리가 아닌, JOIN을 사용하면 아래와같이 표시될 수 있다.
select d.*, sum(e.salary) as sum from Department d join Employee e on d.department_id = e.department_id group by e.department_id;

select d.*, sum from Department d, (select department_id,sum(salary) as sum from Employee group by department_id) as e where d.department_id = e.department_id;

- 주의 해야할점은, from절의 경우 카테시안 곱문제의 발생 가능성을 염두해야 한다는 점이다.
- 아래의 쿼리를 살펴보겠다.
select d.*, sum(e.salary) as sum from Department d, (select * from Employee) as e where d.department_id = e.department_id group by d.department_id;

- 위 쿼리와 동일하게 작동하는 것처럼 보인다.
- 하지만 아래의 쿼리는 카테시안 곱문제가 발생된 테이블의 데이터목록들 중에서, where,group by 조건을 통해 다시 함축시키는 개념이라면
- 위 쿼리는 카테시안 곱문제를 발생시키지않고 group by로 묶으면서, where 조건문을 적용시킨 모습이다.
Where
- 일반 서브쿼리
- 질문
- A테이블의 department_id가 존재하는 경우에 대해서, B테이블의 데이터를 추출할것.
- B테이블의 데이터의 hire_date가 2020-05-09보다 큰경우만 추출할것.
select * from Employee where department_id in (select department_id from Department where department_id is not null) and hire_date >= '2020-05-09';

TMI
Question
- A테이블의 모든 데이터와, B테이블에서 특정 칼럼만 가져오는 쿼리를, 서브쿼리를 활용하여 가져와 주세요.
My_Answer
select d.*, e.name from Department d, (select * from Employee e wehre e.department_id = d.department_id);
Real_Answer
select d.*, e.name from Department d, (select * from Employee) as e where d.department_id = e.department_id;
의문점
- 위 쿼리와, 아래 쿼리의 차이점은 where절이 서브쿼리 안에 있냐, 밖에있냐 차이인데 무엇이 문제일까?
해소
- 현재 나의 쿼리는 from절에 서브쿼리를 사용한 형태이다.
- from절에 사용되는 서브쿼리의 경우, 바깥 쿼리의 정보를 가져 올 수없기떄문에 문제가 발생된 모습이다.
- select, where절에 사용되는 서브쿼리는 바깥 쿼리의 정보를 가져 올 수 있다.
참조문헌
https://suy379.tistory.com/106