본문 바로가기

SQL

Subquery

Subquery vs Join


서브쿼리와 조인 모두 다른 테이블에서 데이터를 가져와 합친다.

  1. Subquery
  • 하나의 쿼리로서 단독으로 수행될 수 있다.
  • 한 개의 결과값 또는 row set 을 반환한다.
  • 서브쿼리의 결과는 바로 사용된다.
  1. Join
  • 단독으로 수행 불가능. 하나 이상의 테이블에서 매칭 조건에 기반해 레코드를 합친다.
  • row set 만 반환한다.
  • 조인된 테이블은 outer query에서 사용될 수 있다.

Subquery Guidelines


  1. 서브쿼리는 반드시 괄호() 로 감싸야 한다.
  2. 비교 연산자 오른쪽에 위치해야 한다.
-- Example
SELECT <column> FROM <table>
WHERE X > = (SELECT MAX(<column>) FROM <table> WHERE <condition>);
  1. 서브쿼리의 결과를 내부적으로 조작할 수 없다.
  2. single-row subquery 에는 single-row operator 를 사용해야 한다.
  3. Null 값을 반환하는 서브쿼리는 결과를 리턴하지 않을 수 있다.

Type of Subqueries


single row: 0~1개의 row를 반환

-- Example
-- Q. Salary that is larger than the average salary
SELECT salary
FROM salaries
WHERE salry = (SELECT AVG(salary) FROM salaries);

multiple row: 1개 이상의 row를 반환

-- Example
-- Q. Product that is in category Comedy, Family, Classics

SELECT title, price, category
FROM products
WHERE category IN (
    SELECT category FROM categories
    WHERE categoryname IN ('Comedy', 'Family', 'Classics')
);

multiple column: 1개 이상의 column을 반환

-- Example
-- Q. Employee who receives salary that is larger than department average salary

SELECT emp_no, salary, dea.avg AS "Department average salary"
FROM salaries AS s
JOIN dept_emp AS de USING (emp_no)
JOIN (
    SELECT dept_no, AVG(salary) FROM salaries AS s2
    JOIN dept_emp AS e using (emp_no)
    GROUP BY dept_no
) AS dea USING (dept_no)
WHERE salary > dea.avg;
emp_no | salary | Department average salary
--------+--------+---------------------------
10005 | 78228 | 55574.879369695531
10005 | 82621 | 55574.879369695531
10005 | 83735 | 55574.879369695531
10005 | 85572 | 55574.879369695531
10005 | 85076 | 55574.879369695531
...

correlated

outer statement 에 있는 하나 이상의 column을 참조함 → 레코드마다 서브쿼리가 실행된다

-- Example
-- Q. Most recent salary?

SELECT emp_no, salary, from_date
FROM salaries AS s
WHERE from_date = (
    SELECT max(s2.from_date)
    FROM salaries AS s2
    WHERE s2.emp_no = s.emp_no --reference s.emp_no
)
ORDER BY emp_no;
emp_no | salary | from_date
--------+--------+------------
10001 | 88958 | 2002-06-22
10002 | 72527 | 2001-08-02
10003 | 43311 | 2001-12-01
10004 | 74057 | 2001-11-27
10005 | 94692 | 2001-09-09
...

'SQL' 카테고리의 다른 글

Index  (0) 2021.09.27
View  (0) 2021.09.27
CASE, NULLIF  (0) 2021.09.27
Window Function  (0) 2021.09.27
UNION, GROUPING SETS, ROLL UP  (0) 2021.09.27