
3. SQL 고급
1. 서브쿼리
2) 서브쿼리 분류

실무에서 가장 많이 사용하는 건 위치에 따른 분류라고 한다
스칼라 서브쿼리는 select 절에서 컬럼 대용으로, 인라인 뷰는 from 절에서 테이블 대용, 중첩 서브쿼리는 where, having 조건절에서 쓰인다
3) 연관 여부에 따른 분류 > 비연관 서브쿼리, 연관 서브쿼리

비연관 서브쿼리는 쿼리 자체로 실행될 수 있고, 메인쿼리와 서브쿼리 간 상호작용이 없다

연관 서브쿼리 판별법
- 서브쿼리 안에서 부모 쿼리의 컬럼을 참조하면 연관 서브쿼리다 = 부모에 있는 컬럼이 서브 쿼리에도 있는 것
- 이때 서브쿼리를 단독 실행하면 E1과 같은 부모 컬럼이 정의되지 않았다는 에러가 발생한다
특징
- 부모 행마다 서브쿼리가 반복 실행되므로, 비연관 서브쿼리보다 실행 부담이 크다
- 이번 경우는 연관 서브쿼리이면서, 쿼리 안에 또 다른 쿼리가 들어 있는 중첩 서브쿼리 구조다
4) 위치에 따른 분류 > 스칼라 서브쿼리, 인라인 뷰, 중첩 서브쿼리

스칼라 서브쿼리는 원하는 값 하나를 가져올 때 주로 사용한다
메인 쿼리의 컬럼을 참조하고 있으므로, 이번 경우는 연관 서브쿼리다
연관 서브쿼리는 메인 쿼리가 실행되면서 각 행마다 서브쿼리가 함께 실행된다
스칼라 서브쿼리는 컬럼 위치에서 사용되므로, 반환 결과가 반드시 단일 컬럼, 단일 행이어야 한다 - 그렇지 않으면 다중 행/다중 컬럼 오류가 발생한다

인라인 뷰는 테이블처럼 사용하고 싶을 때 사용한다
서브쿼리 결과를 마치 테이블처럼 사용하기 위해 FROM 절에 넣은 서브쿼리이기 때문에 반드시 alias 를 붙여서 사용한다
Q. 왜 굳이 이렇게 사용하지?
GROUP BY로 데이터를 먼저 줄인 뒤 SELECT, JOIN을 하기 때문에, 원본 테이블보다 행 수가 줄어들어 JOIN 이 훨씬 가벼워진다
서브쿼리를 단독으로 실행해도 동작하므로, 비연관 서브쿼리이면서 인라인 뷰


중첩 서브쿼리는 WHERE 절에서 조건을 주기 위해 사용하는 서브쿼리다
이 코드와 같이, department_name만 알고 있을 때 그에 해당하는 department_id를 서브쿼리로 가져와 필터링할 수 있다
주의할 점은 서브쿼리 결과가 여러 행이 나오는데 = 연산자를 사용하면 단일 행 서브쿼리 오류가 발생한다, 이런 경우에는 = 대신 IN을 사용해 여러 값 비교가 가능하도록 해야 한다
5) 반환값 유형에 다른 분류 > 단일 행 서브쿼리, 다중 열 서브쿼리

단일행 서브 쿼리는 값이 하나만 리턴되기 때문에 = 를 사용할 수 있다


IN 연산자는 컬럼이 2개 이상이어도 사용할 수 있는데, 단, 비교 대상 컬럼의 개수와 서브쿼리 반환 컬럼 개수가 같아야 한다
쿼리를 실행하면 DBMS는 문법·권한 오류를 먼저 확인한 뒤, 옵티마이저가 실행 계획을 만든다
옵티마이저는 같은 결과를 더 빠르게 낼 수 있도록 쿼리를 내부적으로 변환한다 - 우리가 코드를 작성해도 FROM 절이나 서브쿼리 작성 순서 그대로 실행되지 않고, 데이터를 가장 빠르게 가져올 수 있는 순서로 바꿔서 실행한다
따라서 서브쿼리를 썼다고 해서 무조건 느려지는 것은 아니며, 실행 계획에 따라 성능이 결정된다
2. 실습
1) SQL 작성

SELECT NAME
FROM CUSTOMERS
WHERE CUSTOMER_ID IN (
SELECT CUSTOMER_ID
FROM LOANS
WHERE BRANCH_ID IN (
SELECT BRANCH_ID
FROM BRANCHES
WHERE LOCATION = 'Busan'
)
);
-- 방법 2. 조인을 해도 됨
SELECT NAME
FROM CUSTOMERS
WHERE CUSTOMER_ID IN (
SELECT CUSTOMER_ID
FROM LOANS l
JOIN BRANCHES b ON l.BRANCH_ID = b.BRANCH_ID
WHERE b.LOCATION = 'Busan'
)
);
SELECT *
FROM TRANSACTIONS
WHERE ACCOUNT_ID IN (
SELECT ACCOUNT_ID
FROM ACCOUNTS
WHERE CUSTOMER_ID = 100
);
SELECT *
FROM ACCOUNTS
WHERE BALANCE = (
SELECT MAX(BALANCE)
FROM ACCOUNTS a
WHERE CUSTOMER_ID = a.CUSTOMER_ID
);
3. UNION & UNION ALL
1) UNION & UNION ALL

UNION 은 SELECT 결과를 합친 뒤 중복을 제거
UNION ALL 은 두 SELECT 결과를 단순히 이어 붙여서 중복 포함 모든 데이터 출력
별도의 중복 제거·정렬 과정이 없으므로 UNION ALL 이 더 빠르다
ORDER BY는 전체 결과 집합에 적용되므로, 맨 마지막 SELECT 뒤에만 쓸 수 있다
alias 는 첫 번째 SELECT 절에서 지정하면 전체 결과에서 그대로 사용할 수 있다
4. 실습
1) SQL 작성

SELECT NAME FROM EMPLOYEES WHERE NAME LIKE '%55%'
UNION ALL
SELECT NAME FROM CUSTOMERS WHERE NAME LIKE '%55%';
SELECT CUSTOMER_ID, BALANCE, 'ACCOUNT' AS TYPE FROM ACCOUNTS WHERE BALANCE >= 90000
UNION ALL
SELECT CUSTOMER_ID, AMOUNT, 'LOAN' AS TYPE FROM LOANS WHERE AMOUNT >= 90000;
SELECT DISTINCT CUSTOMER_ID FROM LOANS WHERE LOAN_DATE >= CURRENT_DATE() - INTERVAL 1 MONTH
UNION
SELECT DISTINCT CUSTOMER_ID FROM ACCOUNTS WHERE ACCOUNT_ID IN (
SELECT ACCOUNT_ID FROM TRANSACTIONS WHERE TRANSACTION_DATE >= CURRENT_DATE() - INTERVAL 1 MONTH
);
'Education > 신한투자증권 프로 디지털 아카데미' 카테고리의 다른 글
| 패키지 구조 어떻게 짰나요? (2) | 2025.08.26 |
|---|---|
| 실무에서는 주로 어떤 SQL 문법을 사용하게 될까요 ? (4) | 2025.08.10 |
| SQL 기초부터 시작하기 (3) | 2025.08.10 |
| 관계형 데이터베이스가 처음이라면 ERD 부터 만들어봅시다 ! (4) | 2025.08.10 |
| React 프론트 프로젝트 완. 료. (11) | 2025.08.03 |