SQL 7일차 23, 생각3

박철민·2021년 7월 27일
0

제로베이스SQL100제

목록 보기
9/19
post-thumbnail

수강날짜 20-07-27

강의명 : 07 NATURAL 조인
강의명 : 생각대로 SQL - 3

NATURAL 조인

두개의 테이블에서 같은 이름을 가진 컴럼 간의 INNER 조인 집합 결과를 출력한다. SQL문 자체가 간소해 지는 방법이다.

실무에서는 잘 쓰이지 않는다.
그럼 왜 배우는가?

이걸 공부하면서 실무에서 가장 많이 쓰이는 INNER JOIN에 대해 깊게 배울수 있기 떄문이다.

예제 환경

CATEGORIES 테이블

PRODUCTS 테이블

실습

select *
  from PRODUCTS a 
natural join
	CATEGORIES b
;

이것을 INNER JOIN으로 표현하면 다음과 같다.

select	  A.CATEGORY_ID, A.PRODUCT_ID
	  	, A.PRODUCT_NAME, B.CATEGORY_NAME
  from PRODUCTS A 
 inner join
 	CATEGORIES B
    on (A.CATEGORY_ID = B.CATEGORY_ID);

NATURAL JOIN을 사용하면 가독성이 떨어진다.
그러므로 INNER JOIN으로 표현한 것이 좋다.

INNER JOIN도 생략이 가능하다.

select	  A.CATEGORY_ID, A.PRODUCT_ID
	  	, A.PRODUCT_NAME, B.CATEGORY_NAME
  from PRODUCTS A ,	CATEGORIES B
 where A.CATEGORY_ID = B.CATEGORY_ID;

실습2
NATURAL JOIN이 좋지 않은 이유
실습 테이블

city 테이블

country 테이블

두 테이블에는 Country_id가 같다. 그러므로 NATURAL JOIN이 가능하겠지?

select *
  from CITY a
natural join country b;

결과가 0개가 나왔다. 이런 일이 왜 벌어지는가?
두 테이블에 공통 속성은 country_id뿐만 아니라 last_update라는 속성도 둘이 동일하게 같고 있다.
이런 경우 city_id가 같으면서 last_update가 같은 경우를 찾기 때문에 결과값이 0개가 나온 것이다.

NATURAL 조인은 그러므로 실무에서 사용하지 않는다.
사용자의 의도와 다른 결과들이 나올 수 있기 떄문이다.

생각대로 SQL - 3

문제 풀이

문제1) 고객의 기본 정보인, 고객 id, 이름,, 이메일과 함께 고객의 주소 address, district, postal_code, phone 번호를 함께 보여주세요. 	

select cus.customer_id, cus.first_name, cus.last_name, cus.email, addr.address, addr.district, addr.postal_code, addr.phone 
  from customer cus
 inner join address addr
    on cus.customer_id = addr.address_id;
 
문제2) 고객의  기본 정보인, 고객 id, 이름,, 이메일과 함께 고객의 주소 address, district, postal_code, phone , city 를 함께 알려주세요. 	
select cus.customer_id, cus.first_name, cus.last_name, cus.email, addr.address, addr.district, addr.postal_code, addr.phone, ci.city 
  from customer cus
 inner join address addr
    on cus.customer_id = addr.address_id
 inner join city ci
    on addr.city_id = ci.city_id ; 
 
문제3) Lima City에 사는 고객의 이름과,, 이메일, phonenumber에 대해서 알려주세요.	

select cus.first_name, cus.last_name, cus.email, addr.phone 
  from customer cus
 inner join address addr
 	on cus.customer_id = addr.address_id
 where addr.city_id in (
 			select city_id
 			  from city
 			 where city = 'Lima');
 

문제4) rental 정보에 추가로, 고객의 이름과, 직원의 이름을 함께 보여주세요.
- 고객의 이름, 직원 이름은 이름과 성을  fullname 컬럼으로만들어서 직원이름/고객이름 2개의 컬럼으로 확인해주세요.	

select sta.first_name || ' ' || sta.last_name as 직원이름, cus.first_name || ' '|| cus.last_name as 고객이름
  from rental ren
 inner join customer cus
    on ren.customer_id = cus.customer_id
 inner join staff sta
	on ren.staff_id = sta.staff_id;


문제5) seth.hannon@sakilacustomer.org 이메일 주소를 가진 고객의  주소 address, address2, postal_code, phone, city 주소를 알려주세요.	


select address, address2, postal_code, phone, city
  from address addr 
 inner join customer cus
    on addr.address_id = cus.address_id 
 inner join city ci
 	on ci.city_id = addr.city_id 
 where email = 'seth.hannon@sakilacustomer.org'; 


문제6) Jon Stephens 직원을 통해 dvd대여를 한 payment 기록 정보를  확인하려고 합니다. 
      - payment_id,  고객 이름 과 성,  rental_id, amount, staff 이름과 성을 알려주세요. 	

select pay.payment_id, cus.first_name || ' ' || cus.last_name as customer_name, rental_id, amount, sta.first_name || ' ' || sta.last_name as staff_name
  from payment pay
 inner join staff sta
    on sta.staff_id  = pay.staff_id
 inner join customer cus
    on pay.customer_id  = cus.customer_id
 where sta.first_name = 'Jon'
   and sta.last_name  = 'Stephens';
      

문제7) 배우가 출연하지 않는 영화의 film_id, title, release_year, rental_rate, length 를 알려주세요. 	

select fi.film_id, fi.title, fi.release_year, fi.rental_rate, fi.length 
  from film fi
  left join film_actor fa
    on fi.film_id = fa.film_id
 where fa.film_id is null ;
 
문제8) store 상점 id별 주소 (address, address2, distict) 와 해당 상점이 위치한 city 주소를 알려주세요. 

select st.store_id, ad.address, ad.address2, ad.district, ci.city 
  from store st
 inner join address ad
    on st.address_id = ad.address_id
 inner join city ci
	on ad.city_id = ci.city_id ;


문제9) 고객의 id 별로 고객의 이름 (first_name, last_name), 이메일, 고객의 주소 (address, district), phone번호, city, country 를 알려주세요. 	

select cu.customer_id, cu.first_name || ' ' || cu.last_name as 이름, cu.email, ad.address || ' ' || ad.district as 주소, ad.phone, ci.city, co.country 
  from customer cu
 inner join address ad
    on cu.address_id = ad.address_id
 inner join city ci
 	on ad.city_id = ci.city_id
 inner join country co
	on ci.country_id = co.country_id ;

문제10) country 가 china 가 아닌 지역에 사는, 고객의 이름(first_name, last_name), email, phonenumber, country, city 를 알려주세요	

select c.first_name || ' ' || c.last_name as 이름, c.email, a.phone, cn.country, ct.city 
  from customer c 
 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 cn
 	on ct.country_id = cn.country_id
 where cn.country != 'china';

문제11) Horror 카테고리 장르에 해당하는 영화의 이름과 description 에 대해서 알려주세요 	

select *
  from film
 inner join film_category
    on film.film_id  = film_category.film_id
 where category_id in( 
	select category_id 
 	  from category
 	 where name = 'Horror');

문제12) Music 장르이면서, 영화길이가 60~180분 사이에 해당하는 영화의 title, description, length 를 알려주세요.
   -  영화 길이가 짧은 순으로 정렬해서 알려주세요. 	

select f.title, f.description, f.length 
  from film f
 inner join film_category fc
    on f.film_id = fc.film_id
 where fc.category_id in (
 		select category_id
 		  from category c 
 		 where c.name = 'Music')
 order by f.length;
 		)
 
 
문제13) actor 테이블을 이용하여,  배우의 ID, 이름, 성 컬럼에 추가로    'Angels Life' 영화에 나온 영화 배우 여부를 Y , N 으로 컬럼을 추가 표기해주세요.  해당 컬럼은 angelslife_flag로 만들어주세요.	         

select a.actor_id , a.first_name, a.last_name , case when a.actor_id in (
		select actor_id
		  from film f
		 inner join film_actor fa 
			on f.film_id  = fa.film_id
		 where f.title ='Angels Life') then 'Y'
		 else 'N'
		 end as angelslife_flag
  from actor a;

문제14) 대여일자가 2005-06-01~ 14일에 해당하는 주문 중에서 , 직원의 이름(이름 성) = 'Mike Hillyer' 이거나  고객의 이름이 (이름 성) ='Gloria Cook'  에 해당 하는 rental 의 모든 정보를 알려주세요.
 - 추가로  직원이름과, 고객이름에 대해서도  fullname 으로 구성해서 알려주세요.	

select r.*
  from rental r
  inner join customer c on r.customer_id = c.customer_id
  inner join staff s 	on r.staff_id = s.staff_id 
  where date(r.rental_date) between '2005-06-01' and '2005-06-14'
    and (
   		s.first_name || ' ' || s.last_name = 'Mike Hillyer'
   		or
   		c.first_name || ' ' || c.last_name = 'Gloria Cook'
   )
  
문제15) 대여일자가 2005-06-01~ 14일에 해당하는 주문 중에서 , 직원의 이름(이름 성) = 'Mike Hillyer' 에 해당 하는 직원에게  구매하지 않은  rental 의 모든 정보를 알려주세요.
 - 추가로  직원이름과, 고객이름에 대해서도  fullname 으로 구성해서 알려주세요.	

select r.*
  from rental r
  inner join staff s 	on r.staff_id = s.staff_id 
  where date(r.rental_date) between '2005-06-01' and '2005-06-14'
  	and (s.first_name || ' ' || s.last_name != 'Mike Hillyer')

다음과 같이 풀이 하였다.

profile
취준좀비 컴공

0개의 댓글