Today I Learn
: 코드카타, 문풀날 연습문제, 복습문제, 파이썬 세션, SQL 사전퀘스트 Lv5
- 코드카타
- 문제 1 프로그래머스 (#26) 입양 시각 구하기(1)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59412
2. 정답 코드:
select hour(datetime) as hour, count(*) as count
from animal_outs
where hour(datetime) between 9 and 19
group by hour
order by hour
- hour(): datetime 타입에서 시간만 추출하는 함수
select
date_format(datetime, '%H') as hour,
count(*) as count
from animal_outs
where date_format(datetime, '%H') between 9 and 19
group by hour
order by hour
- date_format(datetime, '%h'): 소문자 h를 사용하면 0-12시 사이만
- date_format(datetime, '%H'): 대문자 H를 사용하면 0-23시 사이까지
- date_format(datetime, '%h %p'): 소문자 h 사용으로 0-12시 사이 표시하고 소문자 p도 사용하여 AM PM 표시
- but, 이 코드는 문자열을 반환하므로 where 절에서 문자열과 숫자의 비교가 발생함!
- mysql은 내부적으로 이 비교를 수행할 때 문자열을 숫자로 바꾸긴 함
- but 데이터 타입을 제어하는 습관을 길러야함!!
- → +0이나 cast를 사용하는 방법!
SELECT
CAST(DATE_FORMAT(DATETIME, '%H') AS UNSIGNED) AS HOUR,
COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE CAST(DATE_FORMAT(DATETIME, '%H') AS UNSIGNED) BETWEEN 9 AND 19
GROUP BY HOUR
ORDER BY HOUR;
- cast(... as unsigned): 문자열을 숫자형(Integer)으로 변환
SELECT
DATE_FORMAT(DATETIME, '%H') + 0 AS HOUR,
COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE DATE_FORMAT(DATETIME, '%H') BETWEEN '09' AND '19'
GROUP BY HOUR
ORDER BY HOUR;
- 문제 2 프로그래머스 (#27) 진료과별 총 예약 횟수 출력하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/132202
2. 정답 코드
select MCDP_CD as '진료과코드', count(distinct PT_NO) as '5월예약건수'
from appointment
where APNT_YMD between '2022-05-01' and '2022-05-31'
group by MCDP_CD
order by count(distinct PT_NO) asc, MCDP_CD asc
select MCDP_CD as '진료과코드', count(distinct PT_NO) as '5월예약건수'
from appointment
where APNT_YMD like '2022-05%'
group by MCDP_CD
order by count(distinct PT_NO) asc, MCDP_CD asc
- 문제 3 프로그래머스 (#28) 12세 이하인 여자 환자 목록 출력하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/132201
2. 정답 코드
select PT_NAME, PT_NO, GEND_CD, AGE, ifnull(TLNO,'NONE') as TLNO
from patient
where age <= 12 and gend_cd = 'W'
order by age desc, pt_name asc
- 문제 4 프로그래머스 (#29) 인기있는 아이스크림
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/133024
2. 정답 코드
select flavor
from (
select SHIPMENT_ID, FLAVOR, TOTAL_ORDER
from first_half
group by flavor
order by total_order desc, shipment_id asc ) as subquery
select FLAVOR
from first_half
order by total_order desc, shipment_id asc
- 문제 5 프로그래머스 (#30) 자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/151137
2. 정답 코드
select
CAR_TYPE, count(*) as CARS
from car_rental_company_car
where options like '%통풍시트%'
or options like '%열선시트%'
or options like '%가죽시트%'
group by CAR_TYPE
order by CAR_TYPE
select
CAR_TYPE, count(*) as CARS
from car_rental_company_car
where options regexp '통풍시트|열선시트|가죽시트'
group by CAR_TYPE
order by CAR_TYPE
- regexp '목록1|목록2|목록3...': 목록 여러개 중 하나라도 포함하는지 확인
- 문제 6 프로그래머스 (#40) 루시와 엘라 찾기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59046
2. 정답 코드:
select animal_id, name, sex_upon_intake
from animal_ins
where name in ('Lucy','Ella','Pickle','Rogan','Sabrina','Mitty')
- 문제 7 프로그래머스 (#41) 조건에 맞는 도서 리스트 출력하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/144853
2. 정답 코드:
select book_id,
date_format(published_date,'%Y-%m-%d') as published_date
from book
where year(published_date) = '2021' and category = '인문'
order by published_date asc
- 문제 8 프로그래머스 (#42) 평균 일일 대여 요금 구하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/151136
2. 정답 코드:
select round(avg(daily_fee),0) as average_fee
from car_rental_company_car
where car_type = 'SUV'
- 문제 9 프로그래머스 (#45) 3월에 태어난 여성 회원 목록 출력하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/131120
2. 정답 코드:
select member_id, member_name, gender,
date_format(date_of_birth,'%Y-%m-%d')
from member_profile
where month(date_of_birth) = '03'
and gender = 'W'
and tlno is not null
order by member_id asc
- month() 함수는 정수타입을 반환함
- 근데 내가 문자열 '03'과 비교하려 했기 때문에 문자열을 숫자로 변환하려 시도할 것
- but month()의 결과는 앞에 0이 붙지 않은 순수한 숫자임
- 만약 mysql이 문자열 기준으로 비교했다면 '3' = '03'은 거짓(False)이 되어 아무 결과도 안 나왔을 것
- but mysql이 숫자 중심으로 변환해서 비교했기 때문에 '03'이든 '3'이든 상관 없이 숫자 3으로 취급되어 성공적으로 데이터를 찾아낸 것
select member_id, member_name, gender,
date_format(date_of_birth,'%Y-%m-%d')
from member_profile
where month(date_of_birth) = 3
and gender = 'W'
and tlno is not null
order by member_id asc
- 문제 10 프로그래머스 (#47) 모든 레코드 조회하기
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59034
2. 정답 코드:
select *
from animal_ins
order by animal_id asc
- 문제 11 (#54)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59415
2. 정답 코드:
select datetime
from animal_ins
order by datetime desc
limit 1
- 문제 12 (#56)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/157343
2. 정답 코드:
select *
from car_rental_company_car
where options regexp '네비게이션'
order by car_id desc
- 문제 13 (#32)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/144855
2. 정답 코드:
select b.category, sum(sales) as total_sales
from book b
join book_sales bs
on b.book_id = bs.book_id
where bs.sales_date like '2022-01%'
group by b.category
order by b.category
- 문제 14 (#33)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/131533
2. 정답 코드:
select p.product_code, sum(p.price*os.sales_amount) as sales
from product p
join offline_sale os
on p.product_id = os.product_id
group by 1
order by 2 desc, 1 asc
- 문제 15 (#34)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59043
2. 정답 코드:
select i.animal_id, i.name
from animal_ins i
join animal_outs o
on i.animal_id = o.animal_id
where o.datetime <= i.datetime
order by i.datetime asc
- 문제 16 (#35)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59411
2. 정답 코드:
select animal_id, name
from (
select i.animal_id, i.name,
datediff(o.datetime,i.datetime) as days
from animal_ins i
join animal_outs o
on i.animal_id = o.animal_id
order by datediff(o.datetime,i.datetime) desc
limit 2
) a
- 문제 17 (#36)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59045
2. 정답 코드:
select i.animal_id, i.animal_type, i.name
from animal_ins i
join animal_outs o
on i.animal_id = o.animal_id
where (i.sex_upon_intake like ('Intact%'))
and (o.sex_upon_outcome like ('Spayed%')
or o.sex_upon_outcome like ('Neutered%'))
- 문제 18 (#34)
1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/144854
2. 정답 코드:
select
b.book_id,
a.author_name,
date_format(b.published_date,'%Y-%m-%d') as published_date
from book b
join author a
on b.author_id = a.author_id
where b.category = '경제'
order by 3
- 사전퀘스트 Lv 5. 가장 많이 팔린 품목은?
- 내 문제점 (by GEMINI)
- 문법적 순서
- join 앞에 where가 온 것
- 무조건 from-join이 한 세트이고 그 뒤에 필터 where가 와야함
- 스코프(Scope)의 한계와 복잡도
- 바깥쪽 서브쿼리의 값을 안쪽 서브쿼리가 참조하려고 하는데
- 이렇게 서로 다른 층위의 데이터를 연결하면 (상관 서브쿼리)
- 데이터가 많아질 때 기하급수적으로 느려짐
- 바깥쪽 서브쿼리의 값을 안쪽 서브쿼리가 참조하려고 하는데
- Group By의 남용
- 이미 where절에서 최댓값이 행들만 필터링했기 때문에
- 또 group by를 할 필요가 없음
- 이미 where절에서 최댓값이 행들만 필터링했기 때문에
- 문법적 순서
- 가장 확실한 해결방안
- CTE 사용하기!!!
- 문제 2 (각 제품 카테고리별로 가장 많이 팔린 제품의 이름과 총 판매량을 조회하기)
with totalsold_t as (
select
p.product_name,
p.category,
sum(o.quantity) as totalsold
from basic.products p
join basic.orders3 o on p.id = o.productid
group by 1, 2
),
high_totalsold_t as (
select
old_t.category,
old_t.product_name,
row_number() over (partition by old_t.category order by old_t.totalsold desc)
as rnk,
old_t.totalsold
from totalsold_t old_t
)
select category, product_name, totalsold
from high_totalsold_t as high
where rnk = 1
- 사전퀘스트 Lv.5 예산이 가장 큰 프로젝트는?
- 내 문제점
- subquery를 만들지 않아도 됐음
- 어차피 그대로 employees2 테이블 사용하면 됐는데...
- where 절의 scope 위반
- 부서를 연결지어주기 위해서 where절을 추가했지만 옳지 않았던 where절의 사용...
- max()를 불러오는 서브쿼리 내에서 where절을 사용해서 외부쿼리의 부서와 연결지어주면 됨!
- 부서를 연결지어주기 위해서 where절을 추가했지만 옳지 않았던 where절의 사용...
- subquery를 만들지 않아도 됐음
# 내가 작성한 CTE 쿼리
with subquery as (
select
e2.department,
max(e2.salary) as sal
from basic.employees2 e2
group by e2.department
)
select e.name, e.department, e.salary
from basic.employees2 e
join subquery s
on e.department = s.department
and s.sal = e.salary
# 내가 쓴 망한 쿼리
select e.name, e.department, e.salary
from basic.employees2 e
where e.salary = (
select max(subquery.sal)
from
(select
e2.department,
max(e2.salary) as sal
from basic.employees2 e2
group by e2.department
) as subquery
)
and e.department = subquery.department
# 정답 쿼리
select e.name, e.department, e.salary
from basic.employees2 e
where e.salary = (
select max(e2.salary)
from basic.employees2 e2
where e.department = e2.department
)
- 파이썬 연습문제
https://myun0506.tistory.com/52
입출력, 변수, 문자열
1) 입출력 (Input / Output) sep 옵션 (기본값: sep = ' ' (공백))print(2026, 1, 4, sep="/") # 2016/1/4print("사과", "바나나", "포도", sep=", ") # 사과, 바나나, 포도print("2", "0", "2", "6", sep="") # 2026 end 옵션 (기본값: end = '
myun0506.tistory.com
- 파이썬의 date 함수
print('2026','01','05',sep='/')
print(2026,1,5,sep='/')
from datetime import date
today = str(date.today())
clean = today.replace("-","/")
print(clean)
num = input()
num2 = int(num.replace(',',''))
print(num2*2)
num3 = int("".join(n for n in num if n.isdigit()))
print(num3*2)
- 콤마와 공백 포함된 숫자 처리
- cleaned
- map은 두가지 인자를 전달받는데
- 한개는 int라는 함수
- 다른 한개는 (i.strip() for i in data) 라는 Iterable
- map은 두가지 인자를 전달받는데
- cleaned2
- 여기선 한가지 묶음인데
- for문을 돌면서 각각의 i를 strip함수에 적용시키고 int()함수까지 적용시키는 것
- 여기선 한가지 묶음인데
- cleaned
data = input().split(',') # 이미 리스트 반환
cleaned = list(map(int,(i.strip() for i in data)))
avg = int(sum(cleaned) / len(cleaned))
print(avg)
cleaned2 = [int(i.strip()) for i in data] # 리스트 컴프리핸션 사용
avg2 = int(sum(cleaned2) / len(cleaned2))
print(avg2)
- map 함수
- map 함수가 반환하는 것은 map object인데, 이는 리스트는 아니지만 '한번에 하나씩 값을 꺼내줄 수 있는 봉투'와 같음
- sum() 함수는 이 봉투 안에서 값이 다 나올 때까지 하나씩 꺼내서 더하기 때문에, 굳이 리스트라는 실제 바구니에 담아두지 않아도 합계를 구할 수 있는 것
- map(function, iterable)
- 첫번째 인자는 Collable(함수 객체)
- 두번째 인자는 Iterable
- split 함수
- 공백을 기준으로 리스트를 만듦
- 리스트 컴프리핸션 [ ]
- 그 안에 적힌 내용을 그대로 리스트의 요소로 집어 넣음
- map은 그 자체로 숫자 꾸러미가 아니라 숫자를 만드는 기능일 뿐이라서
- list()를 써서 기능을 실행시키거나 컴프리핸션으로 하나씩 꺼내 담아야 리스트가 됨
data = input()
data2 = map(int,data.replace(',','').split())
print(sum(data))
# 리스트 안에서 직접 정수 변환 반복
data3 = [int(i) for i in data.replace(',','').split()]
print(sum(data))
# map 객체 안의 결과물을 실제 리스트로 변환
data4 = list(map(int, data.replace(',','').split()))
print(sum(data)) # 이제 [100, 200] 형태가 되어 잘 작동합니다.
- 파이썬의 문자열은 불변인 객체이므로 인덱싱을 통한 수정이나 할당 불가능함
s = "OXOXO"
# s[0] = "X" # 에러 발생
print(s)
- 시작과 끝 인덱스가 같으면 범위 없음
s = "Python"
print(f"'{s[0:0]}'") # 빈 문자열 '' 출력
# 설명: 시작과 끝 인덱스가 같으면 빈 문자열이 반환됩니다.
- 인덱싱과 슬라이싱의 차이
s = "Python"
print(s[-1],type(s[-1]))
print(s[-1:],type(s[-1:]))
# 결과는 같아보이지만 사실 차이가 있음
# 인덱싱을 한 것은 마지막 문자 하나를 불러오지만
# 슬라이싱을 한 것은 마지막 문자 하나를 포함한 부분 문자열을 불러옴
list = [1,2,3,4,5]
print(list[-1],type(list[-1])) # 5 int
print(list[-1:],type(list[-1:])) # [5] list
- join()
text = "A,B,C"
split_text = text.split(',')
result = "-".join(split_text)
print(result)
- count()
text = "banana"
print(text.count("na")) # 2
- find()
data = "name: 적토마"
idx = data.find(":")
name = data[idx+1:].strip()
print(name)
- 심화문제 (01_입출력)
ans = input()
if not ans :
print("아무 값도 입력되지 않았습니다.")
else:
print(ans)
- 심화문제 (02_변수)
data = input()
try:
a,b = map(int,data.split())
print(a+b)
print(a-b)
print(a*b)
print(a/b)
except ValueError:
print("옳지 않은 값을 입력했습니다.")
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
- 심화문제 (03_문자열)
- 경로 문자열에서 \n 문제가 생기는 예시와 raw 문자열로 해결하는 예시는?
# 경로 문자열에 \n과 같은 문자열이 있을 때 이를 경로로 받아들이는게 아니라 행 띄움 표시로 이해할 수 있으므로
# r"\n"식으로 작성하면 문자열 전체를 그대로 받아옴
path = r'\n\t\n\r\tn\r\t\t\t'
print(path)
- (도전) 이메일에서 도메인만 뽑아서 대문자로 출력해 보세요.
email = 'minnie@gmail.com'
ind1 = email.find('@')
ind2 = email.find('.')
domain = email[ind1+1:ind2]
print(domain)
'[데이터분석] 부트캠프 TIL' 카테고리의 다른 글
| 20260108 TIL (0) | 2026.01.08 |
|---|---|
| 20260107 TIL (1) | 2026.01.07 |
| 20260105 TIL (0) | 2026.01.05 |
| 20260102 TIL (1) | 2026.01.02 |
| 20260101 TIL (0) | 2026.01.01 |