SQL

[SQL] 서브 쿼리 Subquery

권벡터 2023. 6. 17. 20:34

기본 개념 

정의 

쿼리 안의 또다른 쿼리를 말한다. 서브 쿼리는 조인하지 않은 상태에서 다른 테이블과 일치하는 행을 찾거나, 조인 결과를 다시 조인할 때 사용할 수 있다. 

 

특징 

  • 반드시 소괄호로 감싸 사용한다. 
  • 주 쿼리를 실행하기 전에 1번만 실행한다.
  • 비교 연산자에서 서브 쿼리를 사용하는 경우 서브 쿼리를 오른쪽에 기술해야 한다. 
  • 내부에는 정렬 구문인 ORDER BY 문을 사용할 수 없다. 

활용 

WHERE 문에서 서브 쿼리 사용

WHERE 문에 사용하는 서브 쿼리를 중첩 서브 쿼리(nested subquery) 라고 한다. 

중첩 서브 쿼리는 조건문의 일부로 사용한다. 

서브 쿼리를 비교연산자 [ =, <, <=, >, >=, <>] 와 함께 사용할 때는 반드시 서브커리의 반환 결과가 1건 이하여야 한다.

만약 서브 쿼리를 반환 결과가 2건 이상인 경우에는 다중 행 연산자를 사용해야 한다.

다중 행 연산자의 종류

다중 행 연산자 설명
IN 서브 쿼리의 결과에 존재하는 임의의 값과 같은 조건 검색
ANY 서브 쿼리의 결과에 존재하는 어느 하나의 값이라도 만족하는 조건 검색
EXISTS 서브 쿼리의 결과를 만족하는 값이 존재하는지 여부 확인
ALL 서브 쿼리의 결과에 존재하는 모든 값을 만족하는 조건 검색 

 

단일 행 서브 쿼리 

기본 형식 

SELECT [열 이름]
FROM [테이블]
WHERE [열] = (SELECT [열] FROM [테이블] )

예시

SELECT * FROM nasdaq_company
WHERE symbol = (SELECT symbol FROM nasdaq_company WHERE symbol IN ('MSFT'))

해석 

  1. 나스닥 회사의 테이블을 검색한다.
  2. 나스닥 회사의 'symbol' 의 'MSFT'인 데이터를 검색한다. 

 

다중 행 서브 쿼리

기본 형식 

SELECT [열 이름]
FROM [테이블]
WHERE [열] IN (SELECT [열] FROM [테이블] )

 

IN 사용

SELECT 
  a.industry, 
  c.symbol,
  c.company_name,
  c.ipo_year,
  c.sector
FROM industry_group AS a
  INNER JOIN industry_group_symbol AS b ON a.num = b.num
  INNER JOIN nasdaq_company AS c ON b.symbol = c.symbol 
WHERE a.industry = N'자동차'
ORDER BY symbol 

-- IN 문 서브 쿼리
SELECT
*
FROM nasdaq_company
WHERE symbol IN(
SELECT symbol FROM industry_group AS a
  INNER JOIN industry_group_symbol AS b ON a.num = b.num
WHERE a.industry = N'자동차'
)

해석

  1. 테이블을 작성한다. 
  2. 나스닥 회사의 테이블을 검색한다. 
  3. a 테이블과 b 테이블을 내부 조인 하고 a.industry 가 '자동차' 인 행을 검색한다. 

 

NOT IN 사용 

-- NOT IN 문 서브 쿼리
SELECT
*
FROM nasdaq_company
WHERE symbol NOT IN (
  SELECT symbol FROM industry_group AS a
    INNER JOIN industry_group_symbol ASON a.num = b.num
WHERE a.industry = N'자동차'
)

해석

  1. 나스닥  회사의 테이블을 검색한다. 
  2. a 테이블과 b 테이블을 내부 조인하고 a.industry 가 '자동차'  가 아닌 행을 검색한다. 

 

ANY 사용 

SELECT * FROM nasdaq_company
WHERE symbol = ANY (
  SELECT symbol FROM nasdaq_company
  WHERE symbol IN ('MSFT', 'AMD', 'AMZN'
)

해석

  1. 나스닥 회사의 테이블을 검색한다. 
  2. 나스닥 회사의 symbol 에 'MSFT', 'AMD', 'AMZN' 이 하나라도 만족되는 행을 검색한다.

 

EXIST 사용 

SELECT * FROM nasdaq_company
WHERE EXISTS (
  SELECT symbol FROM nasdaq_company
  WHERE symbol IN ( 'MSFT' , 'AMD' , 'AMZN' )
)

해석

  1. 나스닥 회사의 테이블을 검색한다. 
  2. 해당 조건에 데이터가 존재하면 메인 쿼리를 실행하도록 한다. (NOT EXIST인 경우, 메인쿼리가 실행되지 않음)

 

ALL 사용

SELECT * FROM nasdaq_company
WHERE symbol = ALL (
  SELECT symbol FROM nasdaq_company
  WHERE symbol IN ( 'MSFT' , 'AMD' , 'AMZN' )
)

해석

  1. 나스닥 회사의 테이블을 검색한다. 
  2. 위의 조건을 모두 만족하는 데이터를 검색한다. 

FROM 문에 서브 쿼리 사용

기본 형식 

SELECT [열 이름]
FROM [테이블] AS a
INNER JOIN (SELECT [열] FROM [테이블] WHERE [열] = [값]) AS b ON [a.열] = [b.열]
WHERE [열] = [값]

예시

-- 테이블 조인
SELECT 
  a.symbol, a.company_name, a.ipo_year, a.sector, a.industry,
  b.date, b.[open], b.[high], b.[low], b.[close], b.adj_close, b.volume
FROM nasdaq_company AS a
  INNER JOIN stock AS b ON a,symbol = b.symbol 
WHERE a. symbol = 'MSFT'
  AND b.date >= '2021-10-01'
  AND b.date < '2021-11-01'

-- 서브 쿼리
SELECT 
  a.symbol, a.company_name, a.ipo_year, a.sector, a.industry,
  b.date, b.[open], b.[high], b.[low], b.[close], b.adj_close, b.volume
FROM nasdaq_company AS a
  INNER JOIN (SELECT symbol, date [open], [high], [low], [close], adj_close, volume
              FROM stock
              WHERE symbol = 'MSFT'
                AND date >= '2021-10-01'
                AND date < '2021-11-01'
            )   AS b ON a.symbol = b.symbol

해석

  1. 위와 같이 테이블을 작성한다. 
  2. a 테이블과 b 테이블( 논리적으로 격리된)을 내부 조인한 데이터를 검색한다. 

 

SELECT 문에 서브 쿼리 사용 

기본 형식 

SELECT [열 이름],
  ( SELECT <집계 함수> [열 이름] FROM [테이블 2]
    WHERE [테이블 2.열] = [테이블 1.열] ) AS Alias
FROM [테이블 1]
WHERE [조건]

예시

--테이블 조인
SELECT
  a.symbol, a.company_name, a.ipo_year, a.sector, a.industry,
  b.date, b.[open], b.[high], b.[low], b.[close], b.adj_close, b.volume
FROM nasdaq_company AS a
 INNER JOIN stock AS b ON a.symbol = b.symbol
WHERE a.symbol = 'MSFT'
  AND b.date >= '2021-10-01'
  AND b.date  < '2021-11-01'

--서브 쿼리
SELECT
  a.symbol,
  ( SELECT company_name FROM nasdaq_company AS b WHERE b.symbol = a.symbol) AS company_name,
  ( SELECT ipo_year FROM nasdaq_company AS b WHERE b.symbol = a.symbol ) AS ipo_year, 
  ( SELECT sector FROM nasdaq_company AS b WHERE b.symbol = a.symbol) AS sector,
  ( SELECT industry FROM nasdaq_company AS b WHERE b.symbol = a.symbol ) AS industry,
  a.date, a.[open], a.[high], a.[low], a.[close], a.adj_close, a.volume 
FROM stock AS a
WHERE a.symbol = 'MSFT'
  AND a.date >= '2021-10-01'
  AND a.date < '2021-11-01'

 

 

참고