[SQL]서브쿼리,JOIN

2025. 1. 17. 14:57·SQL

3주차 복습하기

   문자 변경

  1. REPLACE : 지정한 문자를 다른 문자로 변경
  2. SUBSTRING : 특정 문자만 추출
  3. CONCAT : 여러 문자를 합하여 포맷팅 

  조건문

  1. IF : if(조건, 조건을 충족할 때, 조건을 충족하지 못할 때)
  2. CASE WHEN END:

                                        case when 조건1 then 값(수식)1

                                                 when 조건2 then 값(수식)2

                                                 else 값(수식)3

                                         end

                                        


4주차에는 여러번의 연산을 한번의 SQL 문으로 실행할수 있는 Subquery와 Join 에 대해서 알아보자

 

서브 쿼리(Subquery)

서브 쿼리가 필요한이유

1.여러번의 연산을 수행해야 할때

2.조건문에 연산 결과를 사용해야 할 때

3.조건에 Query 결과를 사용하고 싶을때

 

서브쿼리의 기본구조

ex1)

select column1, special_column
from
    (
    select column1, column2 special_column
    from table1
    )

 

ex2)

select column1, column2
from table1
where column1 = (select col1 from table2)

 

이해를 돕기 위해 실습으로 진행해보자

 

1. [실습] 음식점의 평균 단가별 segmentation 을 진행하고, 그룹에 따라 수수료 연산하기

(수수료 구간 -

~5000원 미만 0.05%

~20000원 미만 1%

~30000원 미만 2%

30000원 초과 3%)

select restaurant_name ,
      avgprice*add_avgprice as '수수료'
from (select restaurant_name,
             case when avgprice<5000 then 0.005
                  when avgprice between 5000 and 19999 then 0.01
                  when avgprice between 20000 and 29999 then 0.02
                  else 0.03 
             end add_avgprice,avgprice
      from (select restaurant_name, avg(price/quantity) as avgprice
            from food_orders
            group by restaurant_name) a)b

 

※코드분석

restaurant_name을 그룹별로 묶어 평균 단가를 측정 -> 평균단가를 수수료 기준에 따라 다르게 계산한다 -> 평균단가와 기준에따른 수수료를 곱하여 값을 출력한다.

 

2. [실습] 음식 타입별 총 주문수량과 음식점 수를 연산하고, 주문수량과 음식점수 별 수수료율 산정하기

(음식점수 5개 이상, 주문수 30개 이상 → 수수료 0.005%

 음식점수 5개 이상, 주문수 30개 미만 → 수수료 0.008%

 음식점수 5개 미만, 주문수 30개 이상 → 수수료 0.01%

 음식점수 5개 미만, 주문수 30개 미만 → 수수료 0.02%)

select cuisine_type,ord_count,res_count,
       Case when res_count >=5 and ord_count>=30 then 0.005
            when res_count >=5 and ord_count<30 then 0.008
            when res_count <5 and ord_count>=30 then 0.01
            when res_count <5 and ord_count<30 then 0.02
       end as ratio_price
from (select cuisine_type,sum(quantity) as ord_count,count(distinct restaurant_name) as res_count
      from food_orders
      group by 1)a

 

3. [실습] 음식점의 총 주문수량과 주문 금액을 연산하고, 주문 수량을 기반으로 수수료 할인율 구하기

(할인조건 수량이 5개 이하 → 10% 수량이 15개 초과, 총 주문금액이 300000 이상 → 0.5% 이 외에는 일괄 1%)

select restaurant_name,
       Case when total_order<=5 then 0.1
            when total_order>15 and total_price>=300000 then 0.005
            else 0.01
       end '수수료'
from(select restaurant_name,SUM(quantity) as total_order,SUM(price) as total_price
     from food_orders
     group by 1)a

 

 

조인(JOIN)

조인이 필요한 이유

ex 1) 주문 가격은 주문테이블에 있지만, 어떤 수단으로 결제를 했는지는 결제테이블에 있을때

ex 2) 주문을 한 사람을 확인하기 위해, 주문 테이블과 고객 테이블에서 각각 정보를 가져와서 엑셀에서 합쳐야 할때

 

 

위 그림과 같이 다른 테이블에 같은 컬럼(고객 id)가 있을때 한 테이블로 묶어줄 수 있다.

 

조인의 종류(LEFT JOIN,INNER JOIN,FULL JOIN)

 

LEFT,RIGHT JOIN : 공통 컬럼 (키값) 을 기준으로, 하나의 테이블에 값이 없더라도 모두 조회되는 경우를 의미함.

INNER JOIN : 공통 컬럼 (키값) 을 기준으로, 두 테이블 모두에 있는 값만 조회함.

FULL JOIN: 모든 컬럼을 기준으로,두 테이블 모두에 있는 값 조회

 

기본구조

- LEFT JOIN
select 조회 할 컬럼
from 테이블1 a left join 테이블2 b on a.공통컬럼명=b.공통컬럼명


- INNER JOIN
select 조회 할 컬럼
from 테이블1 a inner join 테이블2 b on a.공통컬럼명=b.공통컬럼명

 

 

JOIN 으로 두 테이블의 데이터 조회하기

1) [실습] 한국 음식의 주문별 결제 수단과 수수료율을 조회하기

(조회 컬럼 : 주문 번호, 식당 이름, 주문 가격, 결제 수단, 수수료율)

*결제 정보가 없는 경우도 포함하여 조회

select a.order_id,a.restaurant_name,a.price ,b.pay_type ,b.vat
from food_orders a left join payments b on a.order_id=b.order_id
where cuisine_type='Korean'

 

2) [실습] 고객의 주문 식당 조회하기

(조회 컬럼 : 고객 이름, 연령, 성별, 주문 식당)

*고객명으로 정렬, 중복 없도록 조회

select distinct c.name,c.age,c.gender,f.restaurant_name
from food_orders f left join customers c on f.customer_id = c.customer_id 
order by c.name

 

 

 

JOIN 으로 두 테이블의 값을 연산하기

1) [실습] 주문 가격과 수수료율을 곱하여 주문별 수수료 구하기

(조회 컬럼 : 주문 번호, 식당 이름, 주문 가격, 수수료율, 수수료)

*수수료율이 있는 경우만 조회

select f.order_id,
       f.restaurant_name,
       f.price,
       p.vat,
       f.price * p.vat vat2
from food_orders f inner join payments p on f.order_id=p.order_id

 

2) [실습] 50세 이상 고객의 연령에 따라 경로 할인율을 적용하고, 음식 타입별로 원래 가격과 할인 적용 가격 합을 구하기

(조회 컬럼 : 음식 타입, 원래 가격, 할인 적용 가격, 할인 가격)

*할인 : (나이-50)*0.005 * 고객 정보가 없는 경우도 포함하여 조회, 할인 금액이 큰 순서대로 정렬

select a.cuisine_type,
       sum(price),
       sum(price*discount_rate) discounted_price
from
(select f.cuisine_type,
       f.price,
       c.age,
       (c.age-50)*0.005 discount_rate
from food_orders f left join customers c on f.customer_id = c.customer_id
where c.age>=50)a
group by 1
order by SUM(price - (price * discount_rate)) desc

 

코드해석

우선 from 절안에서 food_orders 와 cutomers 테이블에 동일한 cutomer_id 를 join 을 통해 합친후 할인율을 구하고 음식타입별로 그룹을 묶어 가격의 합계와 할인가격의합을 구한다

 

4주차 마무리 문제

식당별 평균 음식 주문 금액과 주문자의 평균 연령을 기반으로 Segmentation 하기

  • 평균 음식 주문 금액 기준 : 5,000 이하 / ~10,000 / ~30,000 / 30,000 초과
  • 평균 연령 : ~ 20대 / 30대 / 40대 / 50대 이상
  • 두 테이블 모두에 데이터가 있는 경우만 조회, 식당 이름 순으로 오름차순 정렬
  •  
  •  
select f.restaurant_name,
       Case when avg(f.price)<=5000 then 'price group1'
            when avg(f.price) between 5000 and 10000 then 'price group2'
            when avg(f.price) between 10000 and 30000 then 'price group3'
            when avg(f.price) >=30000 then 'price group4'
       end 'price group',
        Case when avg(c.age) <=29 then 'age group1'
             when avg(c.age) between 30 and 39 then 'age group2'
             when avg(c.age) between 40 and 49 then 'age group3'
             when avg(c.age) >=50 then 'age group4'
       end 'age group'
from food_orders f inner join customers c on f.customer_id =c.customer_id 
group by 1
order by 1

 

위는 안좋은 예시다(내가 썻던 방법) 

이유: 나이와 가격을 평균내는것을 일일이 입력하여 쓸대없이 코드가 복잡해졌다.

from 절을 함수처럼 사용하면 아래와 같이 바꿀수 있을것같다

select restaurant_name,

case when price <=5000 then 'price_group1'

when price >5000 and price <=10000 then 'price_group2'

when price >10000 and price <=30000 then 'price_group3'

when price >30000 then 'price_group4' end price_group,

case when age <30 then 'age_group1'

when age between 30 and 39 then 'age_group2'

when age between 40 and 49 then 'age_group3'

else 'age_group4' end age_group

from

(

select a.restaurant_name,

avg(price) price,

avg(age) age

from food_orders a inner join customers b on a.customer_id=b.customer_id

group by 1

) t

order by 1

 

 

'SQL' 카테고리의 다른 글

[SQL]CSV 파일을 이용해 데이터 가져오기(MY SQL)  (0) 2025.01.20
[SQL]불필요한 Query 처리방법(coalesce,<>), Pivot Table  (0) 2025.01.17
[SQL]REPLACE, SUBSTRING, CONCAT,IF, CASE  (2) 2025.01.16
[SQL]SELECT,WHERE,ORDER BY  (0) 2025.01.14
[SQL]SQL의 개요  (0) 2025.01.14
'SQL' 카테고리의 다른 글
  • [SQL]CSV 파일을 이용해 데이터 가져오기(MY SQL)
  • [SQL]불필요한 Query 처리방법(coalesce,<>), Pivot Table
  • [SQL]REPLACE, SUBSTRING, CONCAT,IF, CASE
  • [SQL]SELECT,WHERE,ORDER BY
코딩로봇
코딩로봇
금융 IT 개발자
  • 코딩로봇
    쟈니의 일지
    코딩로봇
  • 전체
    오늘
    어제
    • 분류 전체보기 (152)
      • JavaScript (8)
      • SQL (11)
      • 코딩테스트 (30)
        • Java (15)
        • SQL (13)
      • Java (10)
      • 프로젝트 (30)
        • 트러블슈팅 (10)
        • 프로젝트 회고 (18)
      • git,Github (2)
      • TIL (38)
      • Spring (20)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    java #arraylist #list #배열
    스파르타 코딩 #부트캠프 #첫ot
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩로봇
[SQL]서브쿼리,JOIN
상단으로

티스토리툴바