TIL_[SQL] Confirmation Rate + python 개인과제

김희정·2024년 1월 5일

TIL

목록 보기
26/57

코드카타

1934. Confirmation Rate

Input: 
Signups table:
+---------+---------------------+
| user_id | time_stamp          |
+---------+---------------------+
| 3       | 2020-03-21 10:16:13 |
| 7       | 2020-01-04 13:57:59 |
| 2       | 2020-07-29 23:09:44 |
| 6       | 2020-12-09 10:39:37 |
+---------+---------------------+
Confirmations table:
+---------+---------------------+-----------+
| user_id | time_stamp          | action    |
+---------+---------------------+-----------+
| 3       | 2021-01-06 03:30:46 | timeout   |
| 3       | 2021-07-14 14:00:00 | timeout   |
| 7       | 2021-06-12 11:57:29 | confirmed |
| 7       | 2021-06-13 12:58:28 | confirmed |
| 7       | 2021-06-14 13:59:27 | confirmed |
| 2       | 2021-01-22 00:00:00 | confirmed |
| 2       | 2021-02-28 23:59:59 | timeout   |
+---------+---------------------+-----------+
Output: 
+---------+-------------------+
| user_id | confirmation_rate |
+---------+-------------------+
| 6       | 0.00              |
| 3       | 0.00              |
| 7       | 1.00              |
| 2       | 0.50              |
+---------+-------------------+

Confirmations 테이블에서 confirmed된 건들의 confirmation_rate을 구하는 문제이다.

처음으로 혼자서 with문을 써봤다. 여태까지 남의 코드 보고 with문을 따라 써보기만해서
이제 뭔가 0.5단계 성장한 기분 🙂

아무튼 엄청 고민하면서 길게 쿼리를 작성했는데...

(내가 쓴 쿼리)
with cnt as (select user_id, sum(action = 'timeout') "timeout",
            sum(action = 'confirmed') "confirmed",
            sum(action = 'timeout' or action = 'confirmed') "both"
            from confirmations
            group by 1)

select a.user_id,
        ifnull(round(confirmed/`both`,2), 0) "confirmation_rate"
from signups a left join cnt b
on a.user_id=b.user_id
group by 1

다른 사람은 어떻게 풀었는지 궁금해서 찾아보니까
1. 
SELECT
  s.user_id,
  ROUND((SUM(IF(c.action = "confirmed", 1, 0)) / COUNT(*)), 2) AS confirmation_rate
FROM
  Signups s
LEFT JOIN
  Confirmations c ON s.user_id = c.user_id
GROUP BY
  s.user_id;
2.
SELECT 
  s.user_id,
  ROUND(AVG(CASE WHEN c.action="confirmed" THEN 1 ELSE 0 END),2) AS confirmation_rate
FROM signups AS s
LEFT JOIN confirmations AS c
  ON s.user_id = c.user_id
GROUP BY 1

다들 나처럼 with는 쓰지도 않고 select 문에서 계산만 해줬는데
나는 왜 쓸데없이 with까지 써가며 작성을 했던 걸까..🥹🥹

그리고 1. 번 쿼리는 나처럼 전체 count에서 confirmed 결과를 나눠서 평균을 구한건 알겠는데,
2.번 case문을 avg로 감싸기만해도 이렇게 된다고...?!

그리고 두개다 나랑 똑같이 left join 걸려있는데
내껀 id=6 의 confirmations 테이블이 모두 Null 이라 결과가 0이 아닌 Null로 나와서
다른 값으로 치환해줬어야 했는데!
얘네는 왜 안했지??

이해가 안간다.....
담주에 튜터님에게 물어보러 가야겠다....


파이썬 개인과제

개인과제 2번 이메일 유효성 검사 관련 리서치하다가
파이썬용 라이브러리에 이메일 유효성 검사해주는 email-validator가 있다는 걸 알게되었다.
하지만 파이썬 알못인 나에겐 그저 암호처럼만 느껴졌다.

튜터님에게 혹시 그걸로 푸는건지 여쭤보니 그렇게 모듈화해서 푸는 방법도 있는데,
우리 수준에선 알고리즘 능력향상이 목적이니 그렇게 안풀어도 된다 하셨다.

하지만 고지식한 나는
'@' 기호 뒤에는 도메인명이 와야 하며, 도메인명은 '.'을 포함한 하나 이상의 문자로 구성되어야 합니다.
이걸 보고 도메인.com (등등) 이렇게 만들어야하는 줄 알고
이메일 유효성 검색할 때 본 정규표현식이 떠올라 어떻게든 활용하려고 애썼다 ㅎㅎㅎㅎㅎ

import re

pattern = "[a-zA-Z][.][a-zA-Z]"
regex_pattern = re.compile(pattern)
(생략)
if "." in i.split('@')[1] in pattern:

결과는 당연히 내가 원하는 대로 안나왔다.

튜터님께 코드 검토를 요청했더니

야매로 정규표현식을 작성하신게 티가 난다구.... ㅎㅎㅎ헤헿
가장 중요한건
문제를 너무 복잡하게 생각하는데, 복잡하게 생각하지말고 주어진 문제 그대로 해석해서 풀으라 하셨다.

도메인.com 의 굴레에서 벗어난 나는 다시 방향을 찾아서 결국 정답을 찾긴 했으나,
저걸 구하고자 했던 어제 오늘 허비했던 시간이 아깝게 느껴졌다.

문제 3 마라톤 도 분명 처음엔 동명이인까지 거르는게 아니었는데,, 어느 순간 문제에 몇줄 추가가 되어있었다.
아무리 리서치를 해봐도 내가 원하는 상황에 대한 예문도 없고, 설명이 잘 되어 있더라도 내가 그걸 이해해먹을 두뇌가 장착되어있지 않아서 문제 3은 쿨하게 동명이인까진 안거르는 쿼리로 냅다 제출했다.

profile
데이터 애널리스트가 되고 싶은

0개의 댓글