반응형

 

서브쿼리(Subquery)

 

 

개념


하나의 SQL 문 안에 포함되어 있는 또 다른 SQL문을 말한다. 

서브쿼리는 메인쿼리가 서브쿼리를 포함하는 종속적인 관계이다.

 

이제부터 앞에 있는 쿼리 select * from ex 메인 쿼리

(select * from sub_ex) 괄호()안에 있는 쿼리를 서브 쿼리라 칭합니다.

 

서브쿼리(자식쿼리) - 메인쿼리 컬럼 사용 가능

메인쿼리(부모쿼리) - 서브쿼리 컬럼 사용 불가

Java의 상속과 똑같은 개념입니다.

 

종류


중첩 서브쿼리( Nested Subquery ) - WHERE 문에 나타나는 서브쿼리

1.단일

2.복수(다중)

3.다중 컬럼

 

인라인 (Inline View) - FROM 문에 나타나는 서브쿼리

 

스칼라 서브쿼리( Scalar Subquery ) - SELECT 문에 나타나는 서브쿼리

 

 

 

이 세개의 종류는 그냥 외워주세요.


WHERE 중첩 서브쿼리

FROM 인라인 뷰

SELECT 스칼라 서브쿼리 


 

실행 순서


서브쿼리 실행 -> 메인(부모) 쿼리 실행

 

 

사용 이유


예를 들어 회사원 테이블에 김동식 대리보다 급여를 많이 받는 사람을 구하시오.

 

위와 같은 상황이 주어지면 서브쿼리가 없을 경우 우리는 일단

김대리의 급여가 얼만지 모르니까

select salary from employee where name = '김대리' 김대리의 정보를 구한다음

정보를 저장했다가

select name,salary from employee where salary > 김대리 급여 저장한 정보

벌써 피곤합니다.

 

하지만 서브 쿼리를 쓴다면

select name,salary from employee where salary > (select salary from employee where name = '김대리')

한줄로 *깰끔하게 정리가 됩니다.

 

이것은 예시일 뿐입니다. 값을 구할 무조건 PK_id로….

 

*깰끔 : 깔끔의 인터넷 용어

 

한마디로

여러번의 쿼리를 수행해야만 얻을 수 있는 결과를 

하나의 중첩된 SQL문장으로 간편하게 결과를 얻을 수 있게 해줍니다.

 

조건


서브쿼리는 SELECT문으로만 작성 할 수 있다.

(SELECT 쿼리밖에 사용 없는것 이다. SELECT문에만 사용 하는 것이 아니라)

 

반드시 괄호()안에 존재하여야 한다.

 

괄호가 끝나고 끝에 ;(세미콜론) 쓰지 않는다.

 

ORDER BY를 사용 할 수 없다.

 

 

사용 가능


SELECT

FROM

WHERE

HAVING

ORDER BY

INSERT문의 VALUES

UPDATE문의 SET

 

서브쿼리도 별칭(alias) 사용이 가능하다.

 

 

문법


문법에 들어가기 앞서, 공통 테이블 예시

CREATE TABLE employee (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64),
salary INT,
office_worker VARCHAR(64),
)

INSERT INTO employee VALUES(1,'허사장',20000000,'사장');

INSERT INTO employee (name,salary,office_worker) VALUES('유부장',10000000,'부장');
INSERT INTO employee (name,salary,office_worker) VALUES('박차장',5000000,'차장');
INSERT INTO employee (name,salary,office_worker) VALUES('정과장',4000000,'과장');
INSERT INTO employee (name,salary,office_worker) VALUES('정대리',3895000,'대리');
INSERT INTO employee (name,salary,office_worker) VALUES('노사원',2500000,'사원');
INSERT INTO employee (name,salary,office_worker) VALUES('하사원',2000000,'사원');
INSERT INTO employee (name,salary,office_worker) VALUES('길인턴',1000000,'인턴');

SELECT * FROM employee

회사원 정보 테이블

 

서브쿼리는 무조건! 괄호() 감싼 사용해야 한다.

(SELECT ~ 서브쿼리 내용)

 

중첩 서브쿼리 - 단일

#Nested Subquery - 단일 행 
#정대리라는 사람의 직급을 구하시오.
SELECT office_worker
FROM employee
WHERE office_worker = (SELECT office_worker FROM employee WHERE name = '정대리')

 

중첩 서브쿼리 - 복수(다중)

-IN, ANY, ALL, EXISTS 등의 연산자로 얻은 서브쿼리 결과 여러개의 행을 반환.

#Nested Subquery - 복수(다중) 행 
#정대리보다 급여가 높은 사람들을 구하시오.
SELECT *
FROM employee
WHERE salary > (
SELECT salary
FROM employee
WHERE NAME = '정대리')

#직급이 사원인 사람들을 구하시오.
SELECT *
FROM employee
WHERE office_worker IN (
SELECT office_worker
FROM employee
WHERE office_worker = '사원')

 

인라인 (Inline View)

#인라인 뷰(Inline View)
#잘못된 구문 - 꼭 파생 테이블엔 별칭을 정해줘야 합니다.
SELECT * FROM (SELECT * FROM employee WHERE office_worker='사원') (X)
/* SQL 오류 (1248): Every derived table must have its own alias */
#인라인 뷰(Inline View)
#직급이 사원인 사람들의 이름과 급여를 구하시오.
SELECT EX1.name,EX1.salary
FROM (
SELECT *
FROM employee AS Ii
WHERE Ii.office_worker='사원') EX1;

 

스칼라 서브쿼리(Scalar Subquery)

#스칼라 서브쿼리(Scalar Subquery)
#정대리 급여와 테이블 전체 평균 급여를 구하시오.
SELECT name,salary,(
SELECT ROUND(AVG(salary),-1)
FROM employee) AS '평균급여'
FROM employee
WHERE name = '정대리';

 

INSERT  서브쿼리(INSERT Subquery)

#테이블2의 정보를 뽑아서 그 데이터를 테이블1에 넣어준다.
INSERT INTO table1 (SELECT * FROM table2);

 

DELETE 서브쿼리(DELETE Subquery)

#인턴의 정보를 구해와서 삭제한다.
DELETE FROM employee WHERE id = (SELECT id FROM employee where office_worker = '인턴' );

 

UPDATE 문 서브쿼리(UPDATE Subquery)

#인턴에 정보를 구해와서 급여를 10만원 인상한다.
UPDATE employee SET salary=(salary+100000)
WHERE id = (SELECT id FROM employee where office_worker = '인턴' );

 

실컷 설명하고 찬물 끼얹는 말이지만,

MySQL 기준

in 함수와 subquery 성능이 좋지 않으므로 쓰지 않는다.

 

IN ()은 INNER JOIN 혹은 EXISTS로 변환(대체) 가능

NOT IN()은 LEFT OUTER JOIN 혹은 NOT EXISTS로 변환가능하다

 

예제 파일 제공


[MariaDB] Subquery.sql
0.00MB

반응형

+ Recent posts