SQL

250521_내일배움캠프_window function(rank, sum), date_format

baektree 2025. 5. 21. 21:20

어렵지만 하면 할 수록 잘 하고 싶고 무엇보다 재미있다.

초반엔 비기너에게 너무 어려운 과제를 부여하는 게 아닌가 한숨이 나왔으나 막상 해보니 하게 된다.

덕분에 캐글 UX&UI도 익숙해지고, CSV파일도 다운 받아 데이터에 가져올 수 있게 되었다. 

 

역시 일단 해보는 게 중요하구나!


오늘의 학습에 대하여

  • window funtion : 행의 관계를 정의하기 위한 함수로 그룹내의 연산 작업
  • date_format : 날짜형식 데이터를 포맷팅 하기; </aside>

1. 오늘 학습 한 내용을 나만의 언어로 정리하기

  • date__format(datetime, ‘%Y-%m-%d’)
    • 정의: 날짜/시간(datetime) 값을 지정한 형식의 문자열로 변환하는데 사용
    SELECT DATE_FORMAT('2025-05-21 14:30:00', '%Y-%m-%d');
    #2025-05-21
    
    SELECT DATE_FORMAT('2025-05-21 14:30:00', '%H-%i-%s');
    #14:30:00 (H가 24시간제)
    
    SELECT DATE_FORMAT('2025-05-21 14:30:00', '%h-%i-%s %p');
    #02:30:00 PM(h가 12시간제)
    
  • window 함수 → 하나씩 돌아가면서 연산해줘
    • 정의
      • 행의 관계를 정의하기 위한 함수로 그룹 내의 연산을 쉽게 만들어 준다.
    • 예시
      • 주문건수가 많은 순으로 순위를 매기기
      • 한식 식당 전체 주문건수 중에서 A식당이 차지하는 비율 확인하기
      • 쿠폰 100개를 뿌리는데 주문이 많은 소비자 순으로 가중치 적용, 누적하여 뿌리기 1등은 5장, 2등은 3장 등등
    • 구조
      • over: 행마다 훌는 것
      • partition by: 그룹을 나누기 위한 기준
      • order by: 정렬할 컬럼 기준
    • window_function(argument) over (partition by 그룹 기준 컬럼 order by 정렬 기준)
    • sql 예시 각 음식점의 주문건이 해당 음식 타입에서 차지하는 비율을 구하고, 주문건이 낮은 순서대로 정렬했을 때, 누적합 구하기
      • 정답1
        • 문제 : WINDOW 함수(SUM 등)를 사용할 때, SUM으로 동일한 cnt_order 값을 가진 여러 행이 있을 경우, SQL 엔진은 이 값을 한꺼번에 더하는 현상이 발생합니다. cnt_order의 순서를 결정할 명확한 기준이 없으므로 발생한 문제입니다.
        • 따라서 정답2로 동일한 cnt_order 값을 가진 행들이 명확하게 순서가 정해져 누적합이 정상적으로 처리됩니다.
      • select cuisine_type, restaurant_name, cnt_order, sum(cnt_order) over (partition by cuisine_type) sum_cuisine, sum(cnt_order) over (partition by cuisine_type order by cnt_order) cum_cuisine from ( select cuisine_type, restaurant_name, count(*) cnt_order from food_orders group by 1, 2 ) a order by cuisine_type, cnt_order #해석 sum(cnt_order) over (partition by cuisine_type order by cnt_order) cum_cuisine 음식 타입(덩어리)별로 합계를 구하는데, 주문건수 오름차순 정렬을 한 뒤 누적 합계 구할래
      • 정답2
        • ORDER BY 절에 cnt_order 외에 추가적인 열에 순서를 부여할 수 있는 restaurant_name을 포함시켜야 합니다. 이렇게 하면 동일한 cnt_order 값을 가진 행들이 명확하게 순서가 정해져 누적합이 정상적으로 처리됩니다. 누적합을 순서대로 표기하기 위해 order by에 cum_cuisine 을 추가해줍니다.
      • select cuisine_type, restaurant_name, cnt_order, sum(cnt_order) over (partition by cuisine_type) sum_cuisine, sum(cnt_order) over (partition by cuisine_type order by cnt_order, restaurant_name) cum_cuisine from ( select cuisine_type, restaurant_name, count(1) cnt_order from food_orders group by 1, 2 ) a order by cuisine_type , cnt_order, cum_cuisine

2. 학습하며 겪었던 문제점 & 에러

  • 문제1) 음식 타입별, 연령별 주문건수 피벗 뷰 만들기
    • 내가 겪은 문제점?
      • 피벗 뷰 만들기
      select cuisine_type,
      	max(if(new_age='10대',cnt_order, 0)) as '10대',
      	max(if(new_age='20대',cnt_order, 0)) as '20대',
      	max(if(new_age='30대',cnt_order, 0)) as '30대',
      	max(if(new_age='40대',cnt_order, 0)) as '40대',
      	max(if(new_age='50대',cnt_order, 0)) as '50대'
      from
      (
      select f.cuisine_type,
      			case when age between 10 and 19 then '10대'
      			when age between 20 and 29 then '20대'
      			when age between 30 and 39 then '30대'
      			when age between 40 and 49 then '40대'
      			when age between 50 and 59 then '50대' end new_age,
      	    count(*) cnt_order
      from customers c inner join food_orders f on c.customer_id=f.customer_id
      where age between 10 and 59
      group by 1, 2
      ) a 
      group by 1
      
    • 내가 했던 풀이 방식, 왜 틀렸는지?
      • where 절을 이용해서 10대 ~ 50대 필터링 하지 않았음.
    • 앞으로 어떻게 하면 좋을지?
      • where 절을 이용해 필터링 할 것

3. 내일 학습 할 것은 무엇인지

  • [ ] 코드카타 20번 튜터님에게 질문하기
  • [ ] SQL 전반적으로 훑기
    • [ ] 어려운거 복습하기
    • [ ] 코드카타 풀면서 함수나 조건 구문 익히기?

#내일배움캠프 #사전캠프 #TIL