본문 바로가기
SQL 공부

사전캠프 달리기반 퀘스트 01-02

by 나노다 2024. 10. 19.

문제 01 데이터 속 김서방 찾기

“김”씨로 시작하는 이용자들 수를 세어 보기로 했습니다.

name_cnt: “김”씨 성을 가지고 있는 교육생의 수

 

[힌트 보기 전]

SELECT count(1) "name_cnt"
FROM user
WHERE SUBSTR(name, 1, 1) = '김'

 

[힌트 본 후]

한 명이 여러 가입 정보를 가질 수도 있겠구나... 결과에 차이가 없어서 오히려 넘어갈 뻔 했다

중복 없이 세도록 수정해주자

SELECT count(distinct email) "name_cnt"
FROM user
WHERE SUBSTR(name, 1, 1) = '김'

 

문제 02 날짜별 획득포인트 조회하기

이용자들이 잘 활동하고 있는지 보고자 합니다.

포인트가 많을수록 활동을 잘하고 있다고 생각 할 수 있습니다.

날짜별로 획득한 포인트가 점점 늘어나는지 줄어드는지 확인해 봅시다.

created_at: 익명화된 유저들의 아이디(varchar255) average_points: 유저가 획득한 날짜별 평균 포인트(int), 반올림 필수

 

[문제 읽기]

아마 created_at 컬럼 설명을 옮기다가 실수하신 듯... "아이디 생성 날짜(timestamp)" 요 설명이 오는 게 맞을 듯 싶다

average_points도 아마 가입 기간 중 일별 획득 포인트의 평균을 묻고 싶은 듯...? 

아니다... 전체 이용자들의 활동 수준을 포인트 기준으로 확인하고 싶은 거니까

"날짜를 기준으로 전체 이용자의 획득 포인트의 평균을 조회"해야 하나 보다...

그리고 날짜는 시간을 날리고 가져와야하고 평균은 반올림해서 정수 부분만 표현을 해야한다네

반올림시키는 방법은 모르니 검색하고 오자 

 

[반올림 관련 MYsql 함수들]

  • ROUND(숫자, 반올림할 자리수) : 반올림
ROUND(123.777) 
-- 결과 : 124, 자리수 설정 안해주면 소수점 첫째 자리에서 반올림
ROUND(123.7777, 3) 
-- 결과 : 123.778, 입력한 자리수만큼 살아남는다
ROUND(123.7777, -2)
-- 결과 : 100, 자리수를 음수로 입력할 경우 소수점 기준 왼쪽 자리수에서 반올림

 

  • CEILING(숫자) : 올림, 무조건 정수 출력
CEILING(123.333)
-- 결과 : 124, 소수점 이하를 무조건 올려서 정수값을 출력

 

  • TRUNCATE(숫자, 버릴 자리수) : 버림
TRUNCATE(123.7777, 2)
-- 결과 : 123.77, ROUND()와 달리 자리수를 반드시 지정해줘야 함

 

  • FLOOR(숫자) : 버림, 무조건 정수 출력
FLOOR(123.777)
-- 결과 : 123, 소수점 이하를 무조건 버려서 정수값 출력

 

관련 함수를 네 개나 공부했다! 이제 문제를 풀어보자

 

[힌트 보기 전]

  • 첫 시도
SELECT DATE_FORMAT(created_at, '%Y%m%d')  
	, ROUND(avg(`point`)) 
FROM point_users pu 
GROUP BY 1

다른 건 맞게 나오는디, created_at 컬럼을 저렇게 불러오니 문자형 컬럼에 'yyyymmdd' 꼴이 돼버렸다.

날짜값은 유지하되 원하는 정보만 가져오는 방법을 찾아보자 

 

  • 성공
SELECT DATE(DATE_FORMAT(created_at, '%Y-%m-%d')) "created_at" 
	, ROUND(avg(`point`)) "average_points"
FROM point_users pu 
GROUP BY 1

 

  • 알게 된 점
DATE_FORMAT('20241019', '%Y-%m-%d)
-- 출력 2024-10-19
DATE_FORMAT('20241019', '%Y/%m/%d)
-- 출력 2024/10/19
DATE_FORMAT('20241019', '%Y.%m.%d)
-- 출력 2024.10.19
DATE_FORMAT('20241019', '%Y %m %d)
-- 출력 2024 10 19, 다만 이 결과에 DATE()를 씌우면 오류! 공백 때문인 듯

날짜 형식엔 DATETIME과 DATE가 있음. 전자는 시간까지 포함

DATE_FORMAT의 출력값은 문자형이고, 출력 설정을 할 때 다양한 변주가 가능

 

[힌트 본 후]

기존 created_at 컬럼은 DATETIME 형식이었고, 조회할 새 created_at은 DATE 형식인 거였다...

굳이 DATE_FORMAT() 과정을 거칠 필요 없이 바로 DATE()를 씌워버리면 해결이었다...

SELECT DATE(created_at) "created_at" 
	, ROUND(avg(`point`)) "average_points"
FROM point_users
GROUP BY 1