💥 CODEKATA
~ 98문제
오늘의 코드카타 후기 : WITH는 신이야
그리고 98번을 97번인줄 알고 풀어서 그냥 한 문제 더 풀었음 ㄱ-
97) Immediate Food Delivery II
# 1차 코드
SELECT ROUND(SUM(a.tf) / (SELECT COUNT(DISTINCT customer_id) FROM delivery), 2)*100 AS immediate_percentage
FROM (
SELECT
IF(MIN(order_date) = customer_pref_delivery_date, 1, 0) AS tf
FROM delivery
GROUP BY customer_id
) a
⇒ ❌
또 서버 테스트에서 틀림 하 ㄱ-.............
SUM(a.tf) 가 15가 나와야 하는데 대체 왜 자꾸 12가 나오는거지 이해 불가임;;
지피티는 FROM절 서브쿼리에서 또 WHERE 서브쿼리 쓰라는데 왜 쓰는지 이해불가
GROUP BY 랑 MIN으로 최초 주문 날짜 구했자나....? 왜 굳이 WHERE로 구해야지 정답인거지
아~~ 지피티 왈 "이 방식은 고객별 최소 주문일의 값만 알 뿐, 그 주문일에 연관된 customer_pref_delivery_date은 정확히 짝지어지는 것이 아님"
이라네 아하 맞네!
# 2차 코드
SELECT ROUND(SUM(a.tf)*100 / (SELECT COUNT(DISTINCT customer_id) FROM delivery), 2) AS immediate_percentage
FROM (
SELECT IF(MIN(order_date) = MIN(customer_pref_delivery_date), 1, 0) AS tf
FROM delivery
GROUP BY customer_id
) a
⇒ ⭕
헤헷 나의 신 WITH님 없이 풀어보았습니다 우하핛
지피티는 FROM 절에서 GROUP BY 안쓰고 WHERE에다가 또 서브쿼리 웅앵~하는거 알려줬는데,
응 뭔 소린지 모르겠어 내 맘대로 살 거야 말리지 마 난 특별하니까 YEAH
# 1차 코드
SELECT ROUND((COUNT(DISTINCT a1.player_id)) / (SELECT COUNT(DISTINCT player_id) FROM activity), 2) AS fraction
FROM activity a1 JOIN activity a2 ON DATEDIFF(a1.event_date, a2.event_date) = 1 AND a1.player_id = a2.player_id
WHERE a1.event_date > a2.event_date
⇒ ❌
케이스는 통과되는데, 서버 테스트에서 통과가 안됨
아무리 봐도 어디가 틀린지 모르겠어서 지피티한테 물어봄
답은 "첫 로그인 다음 날 재로그인이 핵심"
# 2차 코드
SELECT ROUND((COUNT(a1.player_id)) / (SELECT COUNT(DISTINCT player_id) FROM activity), 2) AS fraction
FROM activity a1 JOIN activity a2 ON DATEDIFF(a1.event_date, a2.event_date) = 1 AND a1.player_id = a2.player_id
WHERE a1.event_date > a2.event_date
GROUP BY a1.player_id
HAVING DATEDIFF(MIN(a1.event_date), MAX(a2.event_date)) = 1
⇒ ❌
ㅇㅣ렇게 짜니까 id별로 fraction이 나와서 에바...그룹바이 쓰면 안될 것 같은데, having은 필요함
집계함수를 써서 첫 로그인이날 다음날 로그인의 차이가 1인걸로 구하고 싶음
WHERE 에다가 MIN MAX 쓰기엔 WHERE절 자체에서는 집계함수를 못써서 안됨 어케해야할까
# 3차 코드
SELECT ROUND(IFNULL(SUM(a.cnt), 0) / (SELECT COUNT(DISTINCT player_id) FROM activity), 2) AS fraction
FROM (
SELECT
player_id, MIN(event_date) AS mindate, MAX(event_date) AS maxdate,
DATE_ADD(MIN(event_date), INTERVAL 1 DAY) nextdate, COUNT(DISTINCT player_id) AS cnt
FROM activity
GROUP BY player_id
HAVING maxdate = nextdate
) a
⇒ ❌
와 진짜 모르겠다 어디가 틀린거 WITH 안쓰고 최대한 효율적으로 짜보려고 하니까 머리 터지겠음
서버테스트 결과가 0이 나와 왤까 아~~~
또 지피티한테 물어봄
“플레이어가 3월1일, 3월2일, 3월4일에 로그인했을 때, maxdate는 3월4일입니다.
그런데 nextdate는 3월2일(3월1일 + 1일)이고, HAVING maxdate = nextdate 조건은 만족하지 않으므로
이 플레이어는 누락됩니다.” 라고 함 아…max로 nextday를 구하면 안되는구나
# 4차 코드
WITH first AS (
SELECT
player_id, event_date, MIN(event_date) AS firstdate, DATE_ADD(MIN(event_date), INTERVAL 1 DAY) AS nextday,
COUNT(DISTINCT player_id) AS cnt
FROM activity
GROUP BY player_id
)
SELECT ROUND(COUNT(DISTINCT a.player_id) / (SELECT COUNT(DISTINCT player_id) FROM activity), 2) AS fraction
FROM activity a JOIN first f ON a.player_id = f.player_id AND a.event_date = f.nextday/
⇒ ⭕
호호 GG치고 WITH 쓰기 ㅎㅎ
역시 WITH는 신이야
자 이제 효율 1등 쿼리 탐방ㄱㄱ
# 효율 1등코드
SELECT ROUND(AVG(b.event_date IS NOT NULL), 2) fraction
FROM (
SELECT player_id, MIN(event_date) event_date FROM activity GROUP BY player_id
) a LEFT JOIN activity b ON a.player_id = b.player_id
AND DATEDIFF(a.event_date, b.event_date) = -1;
⇒
아 젠장~~! 내가 1차로 짰던 코드에서 좀만 수정하면 됐네 ㄱ-…………………………………………..
우울따
'Sparta > CODEKATA' 카테고리의 다른 글
| [250926] 스파르타코딩 본캠프 39일차 (2) | 2025.09.26 |
|---|---|
| [250924] 스파르타코딩 본캠프 37일차 (1) | 2025.09.24 |
| [250919] 스파르타코딩 본캠프 34일차 (0) | 2025.09.19 |
| [250918] 스파르타코딩 본캠프 33일차 (0) | 2025.09.18 |
| [250917] 스파르타코딩 본캠프 32일차 (0) | 2025.09.17 |