Database

mysql - 서브쿼리

  • -
728x90

서브쿼리란 메인 쿼리의 다양한 문법 절 한에 다시 쿼리가 들어가는 것을 말한다.

서브쿼리 개념

서브 쿼리 특징

  • 하나의 쿼리에 포함된 또 하나의 쿼리
  • 서브쿼리는 반드시 괄호 안에 있어야 한다.
  • SELECT, FROM, WHERE, HAVING, ORDER BY 절에 사용 가능하다.
  • INSERT, UPDATE, DELETE 문에도 사용 가능하다.
  • 서브쿼리에는 ;(세미콜론)을 붙이지 않아도 된다.

예제 데이터 - pokemon

-- 조인 연습용 테이블 생성
-- info Table
CREATE TABLE pokemon.SPokemon (
	number INT NOT NULL,
	name VARCHAR(1048) NOT NULL,
	type VARCHAR(1024) NOT NULL,
	PRIMARY KEY(number)
);

-- ability Table
DROP TABLE ability;
CREATE TABLE pokemon.ability (
	number INT NOT NULL,
	height FLOAT,
	weight FLOAT,
	attack INT,
	defense INT,
	speed INT,
	PRIMARY KEY(number)
);
-- Insert data
INSERT INTO SPokemon (number, name, type) 
	VALUES (10, 'caterpie', 'bug');
INSERT INTO SPokemon (number, name, type) 
	VALUES (25, 'pikachu', 'electric');
INSERT INTO SPokemon (number, name, type) 
	VALUES (26, 'raichu', 'electric');
INSERT INTO SPokemon (number, name, type) 
	VALUES (133, 'eevee', 'normal');
INSERT INTO SPokemon (number, name, type) 
	VALUES (152, 'chikorita', 'grass');

INSERT INTO pokemon.ability (`number`,height,weight,attack,defense,speed) VALUES
	 (10,0.3,2.9,30,35,45),
	 (25,0.4,6.0,55,40,90),
	 (125,1.1,30.0,83,57,105),
	 (133,0.3,6.5,55,50,55),
	 (137,0.8,36.5,60,70,40),
	 (152,0.9,6.4,49,65,45),
	 (153,1.2,15.8,62,80,60),
	 (172,0.3,2.0,40,15,60),
	 (470,1.0,25.5,110,130,95);

CREATE TABLE pokemon.mypokemon (
	number INT NOT NULL,
	name VARCHAR(1048) NOT NULL,
	height FLOAT NOT NULL,
	weight FLOAT NOT NULL,
	friendship FLOAT,
	type VARCHAR(1024) NOT NULL,
	PRIMARY KEY(number)
);

INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (10, 'caterpie', 0.3, 2.9, -1.455, bug);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (25, 'pikachu', 0.4, 6, 124.78, electric);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (26, 'raichu', 0.8, 30 ,30.289, electric);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (125, 'electabuzz', 1.1, 30, -10.67, electric);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (133, 'eevee', 0.3, 6.5, 15.988, normal);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (137, 'porygo', 0.8 ,36.5, -0.245, normal);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (152, 'chikorita', 0.9, 6.4, 67.164, grass);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (153, 'bayleef', 1.2, 15.8 ,9.756, grass);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (172, 'pichu', 0.3, 2, 872.1, electric);
INSERT INTO mypokemon (number, name, height, weight, friendship, type) 
	VALUES (470, 'leafeon', 1, 25.5, 3.42, grass);

SELECT * FROM pokemon.mypokemon
SELECT * FROM pokemon.ability;
SELECT * from pokemon.SPokemon;

SELECT절의 서브쿼리

*SELECT 절의 서브쿼리는 반드시 결과 값이 하나의 값이어야 함.

 

요청: 피카츄의 영문이름 키를 가져와 주세요

SELECT number, name, 
(SELECT height FROM ability WHERE number = 25) AS height
FROM SPokemon
WHERE name = 'pikachu';

 

 

FROM절의 서브퀴리

  • 인라인 뷰 서브쿼리라고도 한다.
  • FROM절의 서브쿼리는 반드시 결과 값이 하나의 테이블이어야 한다.
  • 서브쿼리로 만든 테이블은 반드시 별명(alias)을 가져야 한다.

요청: 키 순위가 3순위인 포켓몬의 번호와 키 순위를 가져와 주세요.

SELECT number, height_RANK
FROM (SELECT number, RANK() OVER(ORDER BY height DESC) AS height_RANK
	FROM ability) AS A
WHERE height_RANK = 3;

 

WHERE 절의 서브쿼리

WHERE 절의 서브쿼리는 다른 절의 서브쿼리보다 조금은 더 복잡하다.

 

WHERE 절 서브쿼리 특징

  • 중첩 서브쿼리라고도 한다.
  • WHERE절의 서브쿼리는 반드시 결괏값이 하나의 칼럼이어야 한다.(EXISTS 제외)
    • 하나의 칼럼에는 여러 개의 값이 존재할 수 있다.
  • 연산자와 함께 사용한다.
    • 보통 WHERE [칼럼이름] [연산자] [서브쿼리] 형식으로 사용한다.

서브쿼리에 사용하는 연산자 - 비교연산자

서브쿼리 비교연산자

⭐️비교연산자만 사용 시 WHERE절의 서브쿼리는 반드시 결괏값이 하나의 값이어야 한다.

 

서브쿼리에 사용하는 연산자 - 주요 연산자

서브쿼리 주요연산자

⭐️ 주요 연산자 사용 시 , WHERE절의 서브쿼리는 반드시 결괏값이 하나의 칼럼이어야 한다.

⭐️ 단, EXISTS는 단독으로 사용하며 결괏값이 여러 칼럼이어도 상관없다.

 

요청: 키가 평균 키보다 작은 포켓몬의 번호를 가져와주세요

SELECT number
FROM ability
WHERE height < (SELECT AVG(height) FROM ability);

요청: 공격력이 모든 전기포켓몬의 공격력보다 작은 포켓몬의 번호를 가져와 주세요

SELECT number
FROM mypokemon
WHERE attack < ALL(SELECT attack FROM mypokemon WHERE type = 'electric');

 

요청: 방어력이 모든 전기포켓몬의 공격력보다 하나라도 큰 포켓몬의 번호를 가져와 주세요

SELECT number
FROM mypokemon
WHERE defense > ANY(SELECT attack FROM mypokemon WHERE type = 'electric');

요청: bug 타입의 포렛몬이 있다면 모든 포켓몬의 번호를 가져와 주세요

SELECT number
FROM mypokemon
WHERE EXISTS(SELECT * FROM mypokemon WHERE type = 'bug')

 

 

서브쿼리부터 코드가 이제 복잡해지기 시작한다. sql 코테를 위해서는 눈감고 할 수 있을 정도가 되어야 한다. 반복하자

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.