[ᴘʀᴏɢʀᴀᴍᴍᴇʀꜱ] SQL - 서브 쿼리 (Sub-Query)

NewHa·2023년 11월 5일
1
post-thumbnail

☀️ 서브 쿼리 (Sub-Query)

Sub '하위의, 일부분의' + Query '데이터베이스에 보내는 요청'을 합친 단어로 쿼리 안의 쿼리로 SQL문 안에서 '부품'처럼 일부를 이루는 또 다른 SQL문을 서브 쿼리라고 합니다.

  • 서브 쿼리문은 반드시 괄호로 묶어주어야 합니다.
  • "하나의 값"만 반환할 때 사용할 수 있습니다.

🌿 서브 쿼리의 종류

  1. 단일 값을 리턴하는 서브 쿼리 : 하나의 값을 리턴하는 서브쿼리로, 단일 값을 scalar(스칼라)라고도 해서 이런 서브 쿼리를 scalar sub-query (스칼라 서브 쿼리)라고도 합니다. SELECT 절에서 하나의 컬럼처럼 쓰이거나, WHERE 절에서 조건 표현식과 비교되는 값으로 쓰일 수 있습니다.

  2. 하나의 컬럼에 여러 row들이 있는 형태의 결과를 리턴하는 서브 쿼리 : IN, ANY(SOME), ALL 등의 키워드와 함께 쓰입니다.

  3. 하나의 테이블 형태의 결과(여러 컬럼과 여러 row를 가지는)를 리턴하는 서브쿼리 : 일시적으로 탄생한 테이블을 derived table이라고 하고, 원래 있던 테이블 처럼 사용할 수 있습니다. 대신 반드시 alias를 붙여야 합니다.


🌿 SELECT 절의 서브 쿼리

SELECT 컬럼명, (SELECT 다른컬럼 FROM 테이블2) AS 새컬럼 FROM 테이블1;

  • 원래 테이블에 없던 새로운 컬럼을 추가하는 것입니다.
  • 평균값, 최댓값과 같이 특정 컬럼의 특징을 찾아주는 서브쿼리가 자주 사용됩니다.
-- 예를 들어, 전체 상품의 최댓값을 구하는 서브쿼리를 추가하는 SQL문은 다음과 같습니다.
SELECT *, (SELECT MAX(price) FROM item) AS max_price FROM product_ins;
-- 최댓값이 아닌 평균값이라면 MAX 대신 AVG를 사용하면 됩니다.

🫥 프로그래머스 SQL 코딩테스트 - 자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기 (lv.3)

  • 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하는 문제입니다.
  • 저는 CASE문을 사용하면서 '대여중'인 서브쿼리를 만들어 조회하였습니다.
SELECT (CASE 
        WHEN car_id IN (SELECT car_id
         	FROM car_rental_company_rental_history
         	WHERE start_date <= '2022-10-16' AND end_date >= '2022-10-16')
        THEN '대여중'
        ELSE '대여 가능'
    	END) AS availbility
FROM car_rental_company_rental_history

🌿 WHERE 절의 서브쿼리

SELECT 컬럼명 FROM 테이블명
WHERE 조건컬럼 = (SELECT 컬럼명 FROM 테이블명);
-- 서브쿼리로 조건컬럼에서 골라낼 값들을 조회해서 넣으면 됩니다.
  • 서브 쿼리문을 사용해 조건을 걸 수 있습니다.
-- 예를 들어 가장 비싼 상품을 찾는 WHERE문을 작성한다면 다음과 같습니다.
WHERE price = (SELECT MAX(price) FROM 테이블명);

IN

하나의 값이 아닌 하나의 컬럼에 여러 row값을 반환하는 서브쿼리를 사용해, 서브쿼리 '안에' 있는 값들과 일치하도록 조건을 걸 수 있습니다.

🫥 프로그래머스 SQL 코딩테스트 - 즐겨찾기가 가장 많은 식당 정보 출력하기 (lv.3)

  • REST_INFO 테이블에서 음식종류별로 즐겨찾기수가 가장 많은 식당을 조회하는 문제입니다.
SELECT * FROM rest_info
-- 서브쿼리문의 즐겨찾기값(즐겨찾기 수가 가장 많은 값)에 해당하는 row만 조회합니다.
WHERE favorites 
	-- 음식 종류별로 즐겨찾기 수가 가장 많은 값만 나타내는 서브쿼리문
	IN (SELECT MAX(favorites) FROM rest_info GROUP BY food_type)
GROUP BY food_type;
  • 서브쿼리와 IN키워드를 사용하면 테이블을 JOIN하지 않고도 결과를 구할 수 있는 경우도 있습니다.

ANY/SOME

'~중 하나라도'의 의미로, 서브쿼리의 결과값 중 하나라도 조건을 만족하는 경우가 있으면 TRUE를 리턴합니다.

ALL

'모든' 경우에 조건이 성립해야 TRUE를 리턴합니다.


🌿 FROM 절의 서브 쿼리

서브쿼리가 테이블 형태의 결과를 리턴하는 경우입니다. 이를 Derived Table(파생된, 도출된 테이블)이라고 합니다. Derived Table에는 꼭 alias를 붙여줘야 합니다!

  • alias를 해주지 않으면 다음과 같은 에러가 뜹니다.

🫥 프로그래머스 SQL 코딩테스트 - 중복제거하기 (lv.2)

  • 동물 보호소에 들어온 동물의 이름은 몇 개인지 조회하면서 이름이 NULL인 경우를 제외하고 중복되는 이름은 하나로 쳐서 구하는 문제입니다.
  • GROUP BY로 중복을 제거하며 서브쿼리를 사용해 풀 수 있습니다.
SELECT COUNT(name) 
FROM (SELECT name FROM animal_ins GROUP BY name) AS name_table


profile
백 번을 보면 한 가지는 안다 👀

0개의 댓글