[SQL] 14장. 쿼리 결합하기

김상현·2022년 10월 4일
0

SQL

목록 보기
14/22
post-thumbnail

[손에 잡히는 10분 SQL - 벤 포터 지음, 박남혜 옮김] 책의 학습 후 정리자료입니다.


📍 쿼리 결합 이해하기

  • 대부분의 SQL 쿼리는 하나 이상의 테이블에서 데이터를 가져오는 단일 SELECT 문인데, 여러 쿼리(여러 개의 SELECT 문)를 수행하여 하나의 결과로 가져올 수 도 있다.
  • 이런 결합 쿼리를 집합(Union) 쿼리나 복합(Compound) 쿼리라고 부른다.
  • 결합 쿼리를 사용하는 두 가지 경우의 시나리오가 있다.
    • 여러 테이블에 있는 비슷한 구조의 데이터를 하나의 쿼리롤 가져오는 경우
    • 한 개의 테이블에서 여러 개의 쿼리를 수행하고, 하나의 결과로 가져오는 경우

📍 결합 쿼리 만들기

  • UNION 연산자를 이용하면 SQL 쿼리를 결합할 수 있다.
  • 여러 개의 SELECT 문에서 UNION을 지정하면 그 결과가 하나로 결합된다.

📌 UNION 사용하기

  • UNION을 사용하는 방법은 각각의 SELECT 문 사이에 UNION 키워드를 적기만 하면 된다.

🧷 UNION을 사용한 예제

  • Illinois, Indiana, Michigan 에 있는 고객에 대해 보고해야 한다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')

  • 주(State)에 관계없이 Fun4All 고객을 포함해야 한다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'

  • 위의 두 질문을 결합하려면 각각의 SELECT 문 사이에 UNION 연산자를 사용하면 된다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

  • UNION 연산자 대신 여러 개의 WHERE 절로 같은 쿼리를 만든 예이다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI') OR cust_name = 'Fun4All';

  • 이런 간단한 예제에서는 WHERE 절보다 UNION이 훨씬 복잡하지만, 필터링 조건이 좀 더 복잡하거나 하나의 테이블이 아니라 여러 개의 테이블에서 데이터를 가져와야 할 때 UNION을 사용하면 훨씬 더 간단한 쿼리를 마늘 수 있다.

❗️ 성능 문제

  • 좋은 DBMS는 SELECT 문을 결합하기 위해 내부적으로 쿼리 최적하기를 사용한다.
  • 이론상으로는 성능 관점에서 여러 개의 WHERE 절 조건이나 UNION을 사용하는 것이 아무런 차이가 없어야 한다.
  • 하지만 실제로 대부분의 쿼리 최적화기는 기대하는 만큼의 작업을 해내지 못하기 때문에 어떤 것이 더 좋을지는 직접 테스트해서 확인하는 것이 좋다.

📌 UNION 규칙

  • UNION 결합을 제대로 제어하려면 몇 가지 기본 규칙을 알아야 한다.
    • UNION은 반드시 두 개 이상의 SELECT 문으로 구성되어야 하며, 각각의 명령문은 UNION이라는 키워드로 구분한다(만일 네 개의 SELECT 문이 있다면 UNION 키워드는 세 개가 된다).
    • UNION에서 각 쿼리는 같은 열이나 수식, 그룹 함수를 가져야 한다(일부 DBMS는 심지어 열 순서까지 맞춰야 한다).
    • 열 데이터형은 호환될 수 있다. 정확히 같은 데이터형일 필요는 없지만, DBMS가 내부적으로 변환할 수 있어야 한다(예를 들면 다른 수치형이나 다른 날짜형).

✏️ 유니온 열 이름

  • UNION으로 결합한 SELECT 문의 열 이름이 다르다면, 첫 번째 SELECT 문의 열 이름이 적용된다.
  • 즉, 별칭을 사용해야 한다면 첫 번째 SELECT 문의 열 이름에 적용해야 한다.

📌 중복 행 포함하기와 제거하기

  • UNION은 쿼리 결과에서 자동으로 중복 행을 제거한다.
  • 중복 제거는 UNION의 기본 동작이지만, 원한다면 바꿀 수도 있다.
  • 만약 중복되는 행을 포함해서 모든 행을 가져오고 싶다면, UNION 대신 UNION ALL을 쓰면 된다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';

💡 UNION vs WHERE

  • UNION ALL은 WHERE 절에서 갖고 올 수 없는 결과를 반환한다.
  • 만약 중복된 행을 포함해서 모든 조건과 일치하는 행을 가져와야 한다면, WHERE 절이 아니라 반드시 UNION ALL을 사용해야 한다.

📌 결합 쿼리 결과 정렬하기

  • UNION으로 쿼리를 결합할 때는 딱 하나의 ORDER BY 절을 사용할 수 있는데, 이때 이 ORDER BY 절을 마지막 SELECT 구문 뒤에 와야 한다.
  • 결과의 일부분은 한 방식으로 정렬하고, 다른 일부분은 다른 방식으로 정렬하는 것은 의미가 없기 때문에 여러 개의 ORDER BY 절을 지원하지 않는다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;

💡 여러 개의 테이블 사용하기

  • 여러 테이블에 있는 데이터를 결합하거나 열 이름이 다를 때 UNION을 사용하면 유용하다.
  • 열 이름이 다른 테이블에서도 별칭을 사용해 UNION을 쓸 수 있고, 결과를 하나로 가져올 수 있다.

📍 도전 과제

  1. Orderitems 테이블에서 제품 ID(prod_id)와 수량을 가져오기 위해 두 개의 SELECT 문을 결합하는 SQL 문을 작성하라. 하나는 BNBG로 시작하는 SELECT 문이고 다른 하나는 수량이 딱 100인 제품만 가져오는 SELECT 문이다. 제품 ID로 정렬한다.
SELECT prod_id, quantity
FROM OrderItems
WHERE prod_id LIKE 'BNBG%'
UNION
SELECT prod_id, quantity
FROM OrderItems
WHERE quantity = 100;
ORDER BY prod_id

  1. 방금 작성한 SQL을 하나의 SELECT 문으로 다시 작성하라.
SELECT prod_id, quantity
FROM OrderItems
WHERE prod_id LIKE 'BNBG%' OR quantity = 100;

  1. Products 에 있는 제품명(prod_name)과 Customers 에 있는 고객명(cust_name)을 결합하여 가져오는 SQL 문을 작성하라. 그 결과를 제품명으로 정렬한다.
SELECT prod_name
FROM Products
UNION
SELECT cust_name
FROM Customers
ORDER BY prod_name;

  1. 다음 SQL 문은 무엇이 잘못되었는가?
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state = 'MI'
ORDER BY cust_name
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state = 'IL'
ORDER BY cust_name;
  • UNION 으로 결합된 쿼리는 SQL 문 제일 마지막에 ORDER BY 절을 한 번만 사용할 수 있다.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state = 'MI'
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state = 'IL'
ORDER BY cust_name;

profile
목적 있는 글쓰기

0개의 댓글