데이터 분석/SQL

[day19] SQL 어려워도 슬퍼도 나는 안 우럭 .. / 파이썬 다시 시작 !

경 민 2025. 3. 6. 19:34
더보기
더보기
더보기

👩🏻‍💻  TODAY I LEARN

1. 코드카타

- 코드카타 75번 정리 + 배운 개념 정리

- 어제 푼 코트카타 74번 다시 작성해보기

2. 파이썬 종합반 2주차까지 수강 !! 

3. SQLD 이기적 최신 기출 2회분 + 헷갈리는 개념 정리

오늘은 SQL 코드카타에서 프로그래머스로 푸는 문제들을 다 풀고

leetcode 라는 새로운 사이트로 넘어갔다.

점점 어려워질 일만 있을 것 같았는데

난이도가 좀 낮아져서 머리를 식힐 수 있어 좋았다.

근데 다 영어로 되어있어서 문제를 오해석하는 문제가 생겨벌임.

 

◜◝ ͡ ◜◝ ͡ ◜◝ ͡ ◜◝ ͡ ◜◝

~ 왜인지 쉬운데 안쉬운 느낌 ~

◟◞ ͜ ͜ ◟◞ ͜ ͜ ◟◞◟◞╯

⠀⠀⠀⠀O

⠀⠀⠀⠀⠀°

〃o  ()_()

⊂⌒ ( ´ ^ ﻌ ^);

ヽ_っ_/ ̄ ̄ ̄/

    /___/

 

 

그래도 좀 쉬워진 덕분에 (?) 

드디어 파이썬 종합반 강의를 시작했다 . . !

2주 전에 기초문법강의는 완강했지만 

그동안 SQL만 붙잡아서 그런지 살짝 생경했다.

그래도 colab으로 실습 많이 하면서 들었더니

하나 둘씩 떠오르면서

새로운 내용들을 추가 학습하는 방향으로 공부할 수 있었다.

 

오늘은 2주차 강의 (리스트,튜플,딕셔너리)까지 들었고,

내일부터는 좀 더 본격적으로 반복문 등등을 배울 예정 !

토요일 SQLD 시험이 있기 때문에 모든 시간을 할애할 순 없겠지만

그래도 이번주 안에는

코드카타 기초를 풀 수 있을 정도로 실력을 올려두고싶다.

 

결론은

파 이 팅 이  다  ! ! ! !


 

1. 코드카타

(1-1) 코드카타 75번

Q. 트럭의 대여기록별 총 대여료 (할인율 적용해서)

 

방법1. 등가조인할 수 있도록 새로운 칼럼 생성

SELECT 
    A.HISTORY_ID,
    CASE WHEN D.PLAN_ID IS NULL THEN FLOOR(A.DAILY_FEE * A.DIFFDATE)
    ELSE FLOOR(A.DAILY_FEE * (1-(D.DISCOUNT_RATE/100)) * A.DIFFDATE) 
    END AS FEE
FROM
(SELECT
    C.CAR_ID,
    C.CAR_TYPE,
    H.HISTORY_ID,
    C.DAILY_FEE,
    DATEDIFF(H.END_DATE,H.START_DATE) + 1 AS DIFFDATE,
    CASE WHEN DATEDIFF(H.END_DATE,H.START_DATE) + 1 >= 90 THEN '90일 이상'
        WHEN DATEDIFF(H.END_DATE,H.START_DATE) + 1 >= 30 THEN '30일 이상'
        WHEN DATEDIFF(H.END_DATE,H.START_DATE) + 1 >= 7 THEN '7일 이상'
    ELSE 0 
    END AS DIFFDATE_TYPE
FROM 
    CAR_RENTAL_COMPANY_CAR C
JOIN 
    CAR_RENTAL_COMPANY_RENTAL_HISTORY H ON C.CAR_ID = H.CAR_ID
WHERE 
    C.CAR_TYPE = '트럭') A
LEFT JOIN
    CAR_RENTAL_COMPANY_DISCOUNT_PLAN D 
ON 
	A.CAR_TYPE = D.CAR_TYPE 
    AND 
    A.DIFFDATE_TYPE = D.DURATION_TYPE
ORDER BY FEE DESC, HISTORY_ID DESC

 

⭐️ 막혔던 부분

1️⃣ case when 절은 조건을 순서대로 평가한다.

즉, 첫 번째 조건이 충족되면 그 다음은 보지도 않음.

위 예시로 보면

계산값이 90 이상이면 바로 '90일 이상'을 출력하고 이미 만족했기 때문에 30,7은 비교 안 함

때문에 큰 값부터 조건을 주어야 한다.

 

2️⃣ 대여기간 산정할 때 반드시 +1을 해줄 것 !!!

금방 알아채긴 했지만 처음에는 +1 안 해주고 풀었음

 

 

방법2. convert 형변환 후 비등가조인 (>=)

SELECT 
    H.HISTORY_ID,
    FLOOR(C.DAILY_FEE * (DATEDIFF(H.END_DATE,H.START_DATE) + 1) * 
    (1-IFNULL(MAX(DISCOUNT_RATE),0)/100)) AS FEE
FROM 
    CAR_RENTAL_COMPANY_CAR C
JOIN
    CAR_RENTAL_COMPANY_RENTAL_HISTORY H
ON 
    C.CAR_ID = H.CAR_ID
LEFT JOIN
    CAR_RENTAL_COMPANY_DISCOUNT_PLAN D
ON
    C.CAR_TYPE = D.CAR_TYPE
    AND
    DATEDIFF(H.END_DATE,H.START_DATE) + 1 >= CONVERT(D.DURATION_TYPE,SIGNED)
WHERE 
	C.CAR_TYPE = '트럭'
GROUP BY
	H.HISTORY_ID
ORDER BY 
	FEE DESC, HISTORY_ID DESC

 

방법1이 지금까지 배운 내용을 토대로 푼 아주 기초적인? 쿼리라면

방법2는 새로운 기술?을 써서 더 간결하고 빠르게 작성한 쿼리이다.

 

✔︎ Point 1 형변환해주기

duration_type 이 문자형이니까 숫자형인 datediff와 비교할 수 있도록 똑같이 숫자형으로 변환해주면 된다.

숫자형으로 변환할 때는 SIGNED 혹은 UNSIGNED 을 써주면 된다.

CONVERT(칼럼,SIGNED)
CAST(칼럼 AS SIGNED)

"칼럼을 숫자형으로 변환해줘"

 

✔︎ Point 2 비등가조인해주기

지금까지는 =을 이용한 등가조인만 했는데,

이번에 처음으로 >= 을 이용한 비등가조인을 해봤다.

ON a >= b 

"a값이 b 칼럼의 범위보다 크거나 같으면 b를 출력해줘"

 

‼️ 주의
b 칼럼의 범위가 여러 개일 때에는 만족하는 모든 경우의 수가 다 출력된다.
때문에 마지막 SELECT문에 해당 칼럼을 출력할 때,

MAX로 바꿔줘야 한다.

(1-2) 코드카타 74번 다시 풀어보기

튜터님 쿼리를 다시 한 번 톺아보면서 어제보다 더 확실하게 이해했다.

구하고 싶은 데이터가 뭔지 확실하게 알면 조인에 필요한 테이블이 무엇인지도 알 수 있다.

어떤 데이터를 원하는지를 정의하고 시작하는 사고를 하자!


2.  파이썬 종합반 강의 (~2주차)

1️⃣  리스트

1) . (dot)으로 시작하는 다양한 메서드(Methods)

🔻 a_list = [1,2,3,4,5] 기준으로 차례대로 실행 🔻

    • .append : 항목 추가 (한 개) 
      • a_list.append(1,2,3) ☞ [1,2,3,4,5,[1,2,3]] 
    • .extend : 항목 추가 (여러 개) 
      • a_list.extend(1,2,3) ☞ [1,2,3,4,5,1,2,3]
    • .insert(n,  ) : 항목 삽입
      • a_list.insert(2,10) ☞ [1,2,10,3,4,5]
    • .remove : 항목 제거
      • a_list.remove(3) ☞ [1,2,10,4,5] "숫자 3 제거 "
    • .pop : 항목 제거 + 제거된 항목 반환 / del list[n]: 항목 제거
      • pop_value = a_list.pop(3) "3번째 위치의 값 제거"
      • print(a_list) ☞ [1,2,10,5] 
      • print(pop_value) = 4
      • /
      • del a_list[3] "3번째 위치의 값 제거"
      • print a_list ☞ [1,2,10,5] 
    •  
    • .clear : 전체 항목 제거
      • a_list.clear ☞ []
    • .index : 인덱스
      • print(a_list.index(10)) = 2 "숫자 10의 인덱스"
      • 중복값 있을 경우 맨 앞의 인덱스 출력
    • .count : 개수
      • print(a.list.count(7)) = 0 "숫자 7의 개수"
    • .sort : 항목 정렬 (오름차순)
      • a_list.sort()  print(a_list) ☞ [1,3,5,10]
      • a_list.sort(reverse=True) print(a_list) ☞ [10,5,3,1]
    • .reverse : 항목 역방향 정렬 (not 내림차순)
      • a_list.reverse() print(a_list) ☞ [10,5,3,1]
      • print(a_list[::-1]) 와 동일

2) LEN() : 리스트에서 LEN 함수는 항목의 개수를 구한다.

리스트니까 '길이 = 데이터 개수' 라고 생각하면 됨

 

🔶 예시

grades = [85, 92, 88, 78, 90]
average_grade = sum(grades) / len(grades)
print("평균 성적:", average_grade)

 

2️⃣ 딕셔너리

1) 데이터 추가, 조회 등의 방법이 리스트/튜플과 다르다.

dictionary name['key'] = value

.append 가 아니라 

이 구조로 key-value , value를 수정 혹은 추가할 수 있다.

 

2) 찾을 값을 [] 안에 값을 그대로 넣어줘야 한다. 인덱스 숫자 사용 불가 ! (리스트와의 차이)

 

 

'데이터 분석 > SQL' 카테고리의 다른 글

QCC 3회차  (0) 2025.04.04
[day24] window 함수 - 비율 함수  (0) 2025.03.11
[day17] 졌잘싸.............  (5) 2025.03.05
[day13] SQLD 헷갈리는 부분 정리 ˚。・゚✧  (0) 2025.03.01
[day12] with recursive 재귀문 만들기  (0) 2025.02.28