티스토리 뷰

SQL 코드카타

Q76. 상품을 구매한 회원 비율 구하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/131534

2. 정답 코드:

SELECT
    SUBSTR(SALES_DATE, 1, 4) AS YEAR,
    SUBSTR(SALES_DATE, 6, 2) AS MONTH,
    COUNT(DISTINCT o.USER_ID) AS PURCHASED_USERS,
    ROUND(COUNT(DISTINCT o.USER_ID) / (SELECT COUNT(*) FROM USER_INFO WHERE SUBSTR(JOINED, 1, 4) = '2021'), 1) AS PUCHASED_RATIO
FROM USER_INFO AS u
JOIN ONLINE_SALE AS o
  ON u.USER_ID = o.USER_ID
WHERE SUBSTR(u.JOINED, 1, 4) = '2021'
GROUP BY SUBSTR(SALES_DATE, 1, 4), SUBSTR(SALES_DATE, 6, 2)
ORDER BY YEAR, MONTH;

3. 오류 상황: YEAR, MONTH 값이 NULL로 표시된 행이 생김

4. 시도 방법: Gemini를 활용하여 뭐가 틀렸는지 간단한 힌트만 달라고 함

5. 최종 문제 해결 방법: 2021년에 가입은 했더라도 상품 구매는 안한 회원이 있을 수 있으니 LEFT JOIN을 해서 NULL 값을 남겨놔야 한다고 생각했는데, 그렇게 되면 구매일자가 NULL인 행들이 생기면서 문제가 된다! 그래서 우선 INNER JOIN으로 2021년에 가입했고, 상품 구매 이력까지 있는 회원을 조회하는 쿼리를 메인으로 만들어두고, '2021년에 가입한 전체 회원 수'를 구할 때에만 서브쿼리를 써서 구해주면 오류가 발생되지 않는다!

 

Q77. 1757. Recyclable and Low Fat Products

1. 문제 링크: https://leetcode.com/problems/recyclable-and-low-fat-products/description/

2. 정답 코드:

SELECT product_id
FROM Products
WHERE low_fats = "Y"
  AND recyclable = "Y"
ORDER BY product_id;

 

Q78. 584. Find Customer Referee

1. 문제 링크: https://leetcode.com/problems/find-customer-referee/

2. 정답 코드:

SELECT name
FROM Customer
WHERE referee_id != 2
  OR referee_id IS NULL
ORDER BY name;


Python 코드카타 (https://github.com/heeso0908/codekata.git)

Q1. 두 수의 차

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120803

2. 정답 코드:

def solution(num1, num2):
    answer = num1 - num2
    return answer

 

Q2. 두 수의 곱

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120804

2. 정답 코드:

def solution(num1, num2):
    answer = num1 * num2
    return answer

 

Q3. 몫 구하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120805

2. 정답 코드:

def solution(num1, num2):
    answer = num1 // num2
    return answer

 

Q4. 나이 출력

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120820

2. 정답 코드:

def solution(age):
    answer = 2022 - age + 1
    return answer

 

Q5. 숫자 비교하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120807

2. 정답 코드:

def solution(num1, num2):
    if num1 == num2 :
        answer = 1
    else :
        answer = -1
    return answer

라이브 세션) Python 기초 강의 8일차 - 문풀날 [함수, 모듈]

문풀날 연습문제

문제 1

두 개의 숫자를 받아서 더 큰 값을 반환하는 함수 bigger(a, b)를 만들어 보세요.
예를 들어 bigger(3, 5)를 실행하면 5가 반환되어야 합니다.

# 문제 1

def bigger(a, b) :
  if a > b :
    result = a
  elif a < b :
    result = b
  else :
    result = "서로 다른 숫자를 입력해 주세요."
  return result

print(bigger(3, 5))
# 문제 1 - 삼항연산자

def bigger(a, b) :
  return a if a > b else b

print(bigger(3, 5))

코드 실행 결과

 

문제 2

문자열 하나를 받아서 "안녕하세요, ○○님" 형태로 돌려주는 함수 greet(name)을 만들어 보세요.

예를 들어 greet("민수")를 실행하면 "안녕하세요, 민수님"이 반환되어야 합니다.

# 문제 2

def greet(name) :
  return print(f"안녕하세요, {name}님")

greet("민수")

코드 실행 결과

 

문제 3

정수 하나를 받아서 그 수의 제곱값을 반환하는 함수 square(n)을 만들어 보세요.

예를 들어 square(4)는 16을 반환해야 합니다.

# 문제 3

def square(n) :
  return n**2 

print(square(4))

코드 실행 결과

 

문제 4

아래 함수는 숫자를 2배로 만들려고 만든 함수입니다.

하지만 실행해 보면 원하는 결과가 나오지 않습니다.

이 함수의 문제점을 설명하고 올바르게 고쳐 보세요.

def double(n):
    n * 2

result = double(5)
print(result)
n * 2를 return으로 반환해주지 않아서 계산만 해두고 밖으로 내보내질 못한다

 

▼ 코드 수정

# 문제 4

def double(n) :
  return n * 2

result = double(5)
print(result)

코드 실행 결과

 

문제 5

아래 함수는 리스트의 첫 번째 값을 0으로 바꾸려고 합니다.

하지만 실행 결과를 보면 원래 리스트가 바뀌지 않습니다.

그 이유를 설명하고, 리스트가 실제로 바뀌도록 코드를 수정해 보세요.

def change_first(x):
    x = [0, 2, 3]

nums = [1, 2, 3]
change_first(nums)
print(nums)
전체 리스트를 바꾸는게 아니라 첫번째 값(즉 인덱스 0번째 값)만 지정해서 바꿔줘야 한다


▼ 코드 수정 

# 문제 5

def change_first(x) :
  x[0] = 0

nums = [1, 2, 3]
change_first(nums)
print(nums)

코드 실행 결과

리스트, 딕셔너리, 튜플 = 함수에 주소값으로 전달
리스트, 딕셔너리 = 함수 안에서 수정 가능
int, float, bool = 함수 안에서 수정 불가능

문제 6

아래 함수는 숫자를 1 증가시키려는 함수입니다.

하지만 출력 결과가 예상과 다릅니다.

왜 이런 결과가 나오는지 설명해 보세요.

def add_one(n):
    n = n + 1

x = 10
add_one(x)
print(x)
숫자나 문자열은 한 번 만들어지면 값을 바꿀 수 없기 때문에 return으로 결과 값을 받고 x에 다시 add_one(x) 값을 저장해 줘야 한다

 

▼ 코드 수정 

# 문제 6

def add_one(n) :
  return n + 1

x = 10
x = add_one(x)
print(x)

코드 실행 결과

 

문제 7

아래 함수는 리스트의 모든 값을 0으로 바꾸려고 만든 함수입니다.

하지만 실행 결과는 예상과 다릅니다.

출력 결과를 먼저 예측하고, 왜 그런 결과가 나오는지 설명하세요.

def reset(lst):
    lst = [0, 0, 0]

nums = [1, 2, 3]
reset(nums)
print(nums)
결과 : [1, 2, 3]
리스트 값을 [0, 0, 0] 처럼 저장해주는 것은 새로운 리스트를 변수에 저장하는 것 뿐이지 기존 리스트 값을 수정하는게 아니다  → 인덱스 값으로 하나씩 수정해줘야 한다


▼ 코드 수정 

# 문제 7 - ver.1 return O

def reset(lst):
  for i in range(len(lst)) :
    lst[i] = 0
  return lst

nums = [1, 2, 3]
nums = reset(nums)
print(nums)
# 문제 7 - ver.2 return 삭제

def reset(lst):
  for i in range(len(lst)) :
    lst[i] = 0  # 이미 lst 값 바뀜

nums = [1, 2, 3]
reset(nums)
print(nums)

코드 실행 결과

 

문제 8

아래 함수는 문자열을 모두 대문자로 바꾸려고 만든 함수입니다.

하지만 print 결과가 기대와 다릅니다.

왜 문자열이 바뀌지 않는지 설명하세요.

def make_upper(s):
    s.upper()

text = "hello"
make_upper(text)
print(text)
숫자나 문자열은 한 번 만들어지면 값을 바꿀 수 없기 때문에 return으로 결과 값을 받고 text에 다시 make_upper(text) 값을 저장해 줘야 한다
upper는 원본을 가져오는게 아니라, 복사본을 만들어서 대문자로 바꾸는거다!

 

▼ 코드 수정 

# 문제 8

def make_upper(s):
    return s.upper()

text = "hello"
text = make_upper(text)
print(text)

코드 실행 결과

 

문제 9

math 모듈을 사용하여 원의 넓이를 계산하는 프로그램을 만들어 보세요.

사용 방법:

  • 반지름을 입력받는다.
  • math.pi를 사용하여 원의 넓이(π × r × r)를 계산하는 함수를 만든다.
  • 계산된 넓이를 출력한다.

예시 상황:

반지름이 3이라면, 원의 넓이를 계산해서 출력해야 합니다.

# 문제 9

import math

r = float(input("반지름을 입력하세요: "))

result = math.pi * r * r

print(f'원의 넓이: {result:.2f}')
# 문제 9 - ver.2 함수 사용

import math

def circle_area(r) :
  return math.pi * r * r

r = int(input())
print(circle_area(r))

코드 실행 결과

 

문제 10

random 모듈을 사용하여 주사위 프로그램을 만들어 보세요.

요구사항:

  • 1부터 6 사이의 숫자를 하나 랜덤으로 뽑는 함수를 만든다.
  • 뽑힌 숫자를 화면에 출력한다.
  • 이 함수를 3번 호출해서 주사위를 3번 굴린 결과를 출력한다.

출력 예시:

주사위 결과: 4
주사위 결과: 1
주사위 결과: 6
# 문제 10 - ver.1

import random

for i in range(3):
  print(f'주사위 결과: {random.randint(1, 6)}')
# 문제 10 - ver.2

import random

print(f'주사위 결과: {random.randint(1, 6)}')
print(f'주사위 결과: {random.randint(1, 6)}')
print(f'주사위 결과: {random.randint(1, 6)}')
# 문제 10 - ver.3 함수 사용

import random

def roll() :
  return random.randint(1, 6)

print("주사위 결과: ", roll())
print("주사위 결과: ", roll())
print("주사위 결과: ", roll())
for 문을 사용한 ver.1이 실무에서 더 잘 쓰일 것 같다!

코드 실행 결과


어떤 문제에서는 return을 적어야 하고, 또 어떤 문제에서는 return이 없어도 결과가 잘 나올까?

이해가 잘 되지 않아 생성형 AI에게 질문을 해보았다!

 

생성형 AI 설명)

1. 리스트는 '공유 문서'와 같다

파이썬에서 리스트(nums)를 함수에 전달하는 건, 친구에게 내 공책을 복사해서 주는 게 아니라 "우리 같이 쓰는 구글 문서 주소(링크)를 알려주는 것"과 같다!

  • change_first(nums)라고 함수를 실행하면, 함수는 nums라는 리스트가 저장된 메모리 주소를 똑같이 가리키게 됨
  • 함수 안에서 x[0] = 0이라고 하는 건, 공유 문서의 첫 번째 줄을 수정하는 것과 같음
  • 내가 직접 문서를 수정했으니, 함수가 끝나고 밖으로 나와서 원래 nums를 확인해 봐도 이미 문서 내용은 바뀌어 있는 상태!

그래서 굳이 "바뀐 결과를 돌려줄게!"라고 하는 return이 없어도 원본이 직접 수정됨

 

2. 반대로 숫자는 '개인 공책' 같다

아까 풀었던 문제 6번(add_one 함수)을 생각해보자. 숫자는 리스트와 다르다!

  • 숫자를 함수에 보내는 건, 내 공책의 내용을 복사해서 주는 것과 같음
  • 친구(함수)가 자기한테 있는 복사본에 + 1을 아무리 적어도, 내 원본 공책은 변하지 않음
  • 그래서 숫자의 경우에는 반드시 "계산 다 했어! 자, 여기 결과물이야!"라고 return을 해줘야만 밖에서도 바뀐 값을 쓸 수 있음!

🔍 요약하자면!

  1. 리스트(List): 원본을 직접 건드리는 성격이 있어서 return이 없어도 밖의 데이터가 바뀜 (가변성/Mutable)
  2. 숫자/문자열: 원본을 절대 못 바꾸는 성격이라 반드시 return으로 결과물을 새로 받아야 함 (불변성/Immutable)

오늘은 처음으로 Python 코드카타를 진행해봤다. 아직은 단순한 사칙연산 수준의 문제들이라, 걱정했던 것보다는 비교적 수월하게 풀 수 있었다.

코드카타 기록을 GitHub와 연동해보기도 했는데, 직접 작성한 파일을 업로드해보니 사용법이 훨씬 잘 이해됐다. 특히 README 파일의 역할이 잘 와닿지 않았었는데, 생성형 AI의 도움을 받아 현재 학습 현황을 한눈에 볼 수 있도록 정리해둘 수 있어 만족스러웠다.

이번 주까지 파이썬 종합반을 수강하는 것이 목표였는데, 생각보다 일찍 완강하게 되어 전처리 및 시각화 강의도 미리 들어야 할 것 같다. 추가로 이번 주에는 꼭 데이터 분석 관련 도서를 조금이라도 읽는 것을 목표로 삼아야겠다..!

GitHub 꾸미기 완료-!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함