수강 날짜 21-08-01
강의명 : 03 INTERSECT 연산
강의명 : 04 EXCEPT 연산
강의명 : 생각대로 SQL-5
INTERSECT 연산자는 두 개 이상의 SELECT 문들의 결과 집합을 하나의 결과 집합으로 결합한다.
INTERSECT 연산 문법
SELECT
COLUMN_1_1
, COLUMN_1_2
FROM
TABLE_NAME_1
INTERSECT
SELECT
COLUMN_2_1
, COLUMN_2_2
FROM
TABEL_NAME_2;
UNION과의 차이에 대해 주의할 것
예제를 통해 좀 더 알아보자
employees 테이블
keys 테이블
hipos 테이블
keys 와 hipos테이블에 교집합은 (2, 2002-06-01), (5, 2006-06-01)이 있다.
예제 테이블
select employee_id
from keys
intersect
select employee_id
from hipos;
다른 연산과 비교
select k.employee_id
from keys k, hipos h
where k.employee_id = h.employee_id
select k.employee_id
from keys k
inner join hipos h
on k.employee_id = h.employee_id
똑같은 결과들이다.
INTERSECT쓰는 대신에 INNER JOIN을 더 많이 사용한다.
EXCEPT 연산자는 맨위에 SELECT문의 결과 집합에서 그 알애에 있는 SELECT문의 결과 집합을 제외한 결과를 리턴한다.
EXCEPT 연산 문법
select
column_1_1
, column_1-2
from
table_name_1
except
select
column_2_1
, column_2_2
from
table_nmae_2;
EXCEPT는 차집합을 표현한다.
EXCEPT 연산 실습
예제에 사용되는 테이블
실습
재고가 존재하는 영화의 필름ID와 영화 제목을 추출하여라
select distinct i.film_id, f.title
from inventory i
inner join film f
on f.film_id = i.film_id
order by f.title
그렇다면 재고가 존재하지 않는 영화는 어떻게 추출하는가?
기본 필림 집합 - 재고가 있는 영화 = 재고가 없는 영화!
SELECT film_id, title
FROM film
EXCEPT
SELECT DISTINCT i.film_id, f.title
FROM inventory i
INNER JOIN film f
ON f.film_id = i.film_id
ORDER BY title
위의 결과와 다른 값들이 집계된 것을 알 수 있다.
문제1번) 영화 배우가, 영화 180분 이상의 길이 의 영화에 출연하거나, 영화의 rating 이 R 인 등급에 해당하는 영화에 출연한 영화 배우에 대해서, 영화 배우 ID 와 (180분이상 / R등급영화)에 대한 Flag 컬럼을 알려주세요.
SELECT DISTINCT actor_id, 'over_length' AS flag
FROM film_actor fa
INNER JOIN (
SELECT film_id
FROM film
WHERE length >=180) f
ON fa.film_id = f.film_id
UNION ALL
SELECT DISTINCT actor_id, 'rating_R' AS flag
FROM film_actor fa
INNER JOIN (
SELECT film_id
FROM film
WHERE rating = 'R') f
ON fa.film_id = f.film_id
ORDER BY actor_id
유니온을 한다면 중복을 자동으로 제거해서 편하지만 우리가 원치 않는 결과를 초래할 수도 있기 때문에 UNION ALL사용을 권장한다.
문제2번) R등급의 영화에 출연했던 배우이면서, 동시에, Alone Trip의 영화에 출연한 영화배우의 ID 를 확인해주세요.
SELECT actor_id
FROM film_actor fa
INNER JOIN (
SELECT film_id
FROM film
WHERE rating = 'R') f
ON fa.film_id = f.film_id
INTERSECT
SELECT actor_id
FROM film_actor fa
INNER JOIN (
SELECT film_id
FROM film
WHERE title = 'Alone Trip') f
ON fa.film_id = f.film_id
ORDER BY actor_id
문제3번) G 등급에 해당하는 필름을 찍었으나, 영화를 20편이상 찍지 않은 영화배우의 ID 를 확인해주세요.
SELECT actor_id
FROM film_actor fa1
GROUP BY actor_id
HAVING count(*) < 20
INTERSECT
SELECT DISTINCT actor_id
FROM film_actor fa
INNER JOIN (
SELECT film_id
FROM film
WHERE rating = 'G') f
ON fa.film_id = f.film_id
ORDER BY actor_id
문제4번) 필름 중에서, 필름 카테고리가 Action, Animation, Horror 에 해당하지 않는 필름 아이디를 알려주세요.
SELECT fc.film_id
FROM film_category fc
WHERE fc.category_id IN (
SELECT category_id
FROM category c
WHERE c.name NOT IN ('Action', 'Animation', 'Horror'))
ORDER BY film_id
문제5번) Staff 의 id , 이름, 성 에 대한 데이터와 , Customer 의 id, 이름 , 성에 대한 데이터를 하나의 데이터셋의 형태로 보여주세요.
SELECT DISTINCT staff_id AS id, first_name, last_name, 'staff' AS flag
FROM staff s
UNION ALL
SELECT DISTINCT customer_id AS id, first_name, last_name, 'customer' AS flag
FROM customer c
ORDER BY id
문제6번) 직원과 고객의 이름이 동일한 사람이 혹시 있나요? 있다면, 해당 사람의 이름과 성을 알려주세요.
SELECT first_name, last_name
FROM customer c
INTERSECT
SELECT first_name, last_name
FROM staff s
이름이 동일한 사람이 존재하지 않다는 것을 알 수 있다.
문제7번) 반납이 되지 않은 대여점(store)별 영화 재고 (inventory)와 전체 영화 재고를 같이 구하세요. (union all)
문제가 이해가 되지 않아 정답을 보니 다음을 물어보고 있었다,
반납이 되지 않은 영화 개숫를 대여점별로 집계하고 전체 합계도 같이 표현하라
SELECT null, count(*)
FROM inventory i
WHERE inventory_id in(
SELECT inventory_id
FROM rental r
WHERE return_date IS NULL )
UNION ALL
SELECT store_id, count(*)
FROM inventory i
WHERE inventory_id in(
SELECT inventory_id
FROM rental r
WHERE return_date IS NULL )
GROUP BY store_id
문제8번) 국가(country)별 도시(city)별 매출액, 국가(country)매출액 소계 그리고 전체 매출액을 구하세요. (union all)
SELECT co.country , ct.city, sum(amount) AS rental_amount
FROM payment p
INNER JOIN customer c ON p.customer_id =c.customer_id
INNER JOIN address a ON c.address_id = a.address_id
INNER JOIN city ct ON a.city_id = ct.city_id
INNER JOIN country co ON ct.country_id = co.country_id
GROUP BY co.country_id, ct.city_id
UNION ALL
SELECT co.country, NULL , sum(amount) AS rental_amount
FROM payment p
INNER JOIN customer c ON p.customer_id =c.customer_id
INNER JOIN address a ON c.address_id = a.address_id
INNER JOIN city ct ON a.city_id = ct.city_id
INNER JOIN country co ON ct.country_id = co.country_id
GROUP BY co.country_id
UNION ALL
SELECT NULL, NULL, sum(amount) AS rental_amount
FROM payment p
다음과 같이 나온다.