BACK-END

[MySQL] 서브쿼리 (Sub Query)

gudwns5533 2026. 6. 9. 01:07
서브쿼리 (Sub Query)

 

서브쿼리는 SQL문 안에 들어가는 또 다른 SELECT문을 의미한다.

select ... from where 컬럼 = (select ... );
-- 김사과보다 포인트가 많은 회원을 검색

select point from member where name='김사과'; -- 김사과의 포인트 검색
select * from member wherer point > 150; -- 150보다 많은 멤버의 정보 검색
select * from member where point > (select point from member where name='김사과');
-- 서브 쿼리를 써서 김사과보다 포인트가 많은 회원을 검색할 수 있다.

1. 단일 행 서브쿼리

결과가 하나의 값만 나오는 서브쿼리

-- 포인트가 가장 높은 회원을 검색
select * from member where point = (select max(point) from member);

2. 다중 행 서브쿼리

결과가 여러 개 나오는 서브쿼리 (in, any, all을 사용)

-- 포인트가 200 이상인 userid 목록에 포함된 회원을 검색
select * from member where userid in (select userid from member where point >= 150);

3. from절 서브쿼리

서브쿼리 결과를 임시 테이블처럼 사용하는 방식

select name, point from (select name, point from member where point >= 150) as high_point_member;

4. select절 서브쿼리

조회 결과에 서브쿼리 결과를 함께 보여주는 방식

-- 각 회원의 포인트와 전체 평균 포인트를 함께 검색
select name, point, (select avg(point) from member) as avg_point from member;

5. exists 서브쿼리

존재 여부를 확인할 때 사용

-- 주문 내역이 있는 회원을 검색
select * from member m where not exists (select 1 from orders o where o.member_idx = m.idx);

6. 주문 테이블 생성

create table orders (
    order_id int auto_increment primary key,
    member_idx int not null,
    product_name varchar(100) not null,
    price int not null,
    order_date datetime default now(),
    foreign key (member_idx) references member(idx)
);

insert into orders(member_idx, product_name, price)
values
(1, '키보드', 50000),
(1, '마우스', 30000),
(2, '모니터', 250000),
(2, '노트북 거치대', 40000),
(3, 'USB', 15000),
(4, '노트북', 1200000),
(4, '헤드셋', 90000);

 

6-1. 주문한 적이 있는 회원들만 조회 (in 사용)

select * from member where idx in (select member_idx from orders);

 

6-2. 주문한 적이 없는 회원들만 조회 (not in 사용)

select * from member where idx not in (select member_idx from orders);

 

6-3. 가장 비싼 상품을 주문한 회원 조회

-- 1. orders에서 가장 비싼 가격을 찾기
-- 2. 그 가격의 주문을 한 회원 번호를 찾기
-- 3. 해당 회원 번호를 가진 회원 정보를 조회하기
select * from member where idx = 
(select member_idx from orders where price = (select max(price) from orders));

 

6-4. 가장 비싼 상품을 주문한 회원의 이름과 상품명을 조회

-- join을 활용해서 조회
select m.name, o.product_name, o.price from member m join orders o on m.idx = 
o.member_idx where o.price=(select max(price) from orders);

7. 테이블 복사

create table orders_copy (
    order_id int auto_increment primary key,
    member_idx int not null,
    product_name varchar(100) not null,
    price int not null,
    order_date datetime default now(),
    foreign key (member_idx) references member(idx)
);

-- 기존 테이블의 데이터를 다른 테이블로 복사할 수 있다.
insert into orders_copy(select * from orders);
-- 테이블의 형태가 동일하면 insert 서브쿼리도 가능하다

create table orders_copy_copy(select * from orders);
-- 복사한 테이블로 새로운 테이블을 만들 수도 있다.

8. UNION

  • 여러 개의 select 결과를 하나로 합쳐주는 기능
  • 조회 결과를 위아래로 이어 붙이는 기능
select name, address1 from member where address1 like '서울%'
union
select name, address1 from member where address1 like '부산%';

 

이때, UNION은 중복데이터를 제거하고 합친다.

9. UNION ALL

UNION과 동일하게 select 결과를 합쳐주지만 중복데이터를 제거하지않고 모두 합쳐준다.

10. 사용자 계정

  • 데이터베이스에 접속할 수 있는 로그인 계정
  • root 계정은 모든 권한을 가진 계정이기 때문에 실제 사용 시 위험할 수 있음
  • 프로젝트별로 계정을 따로 만들고, 필요한 권한만 부여하는 것이 일반적이다.
-- create user '계정명'@'접속위치' identified by '비밀번호';

-- localhost : 같은 컴퓨터(내 컴퓨터)에서만 접속 > 외부에서 접근할 수 없음.

-- 'apple'@'%' : 어디서든 접속 가능.

-- 'apple'@'192.168.0.%' : 198.168.0.으로 시작하는 내부망에서만 접속이 가능

-- 'apple'@'192.168.0.10' : 특정 ip에서만 접속 가능 (해킹을 막기 위해)

 

권한부여 방법

-- grant 권한종류 on 데이터베이스명/테이블명 to '계정명'@'접속위치';

-- all : 모든 일반 권한, select, insert, update, delete, create, drop, alger, index

-- ai.* : ai 데이터베이스 안의 모든 테이블 (특정 테이블만 원한 다면 * 대신 테이블 명으로 기입)

-- 권한 회수
revoke delete on 데이터베이스명/테이블명 from '계정명'@'접속위치';

-- 사용자 비밀번호 변경
alter user '계정명'@'접속위치' identified by '변경할 비밀번호';

-- 사용자 삭제
drop user '계정명'@'접속위치';

 

'BACK-END' 카테고리의 다른 글

[MySQL] 뷰 (view)  (0) 2026.06.09
[MySQL] MySQL 함수  (0) 2026.06.09
[MySQL] 정규화  (0) 2026.06.06
[MySQL] DML  (0) 2026.06.05
[MySQL] DDL  (0) 2026.06.05