21회차 라이브세션 과제 sql

포도당·2025년 5월 20일
0

문제1

조건1) 서버별, 월별 게임계정id 수를 중복값 없이 추출해주세요. 월은 첫 접속일자를 기준으로 계산해주세요. 월은 yyyy-mm의 형태로 추출해주세요.

힌트: 월을 추출하는 방법→날짜는 string(문자열) 형식으로 저장되어 있으므로, 문자열을 자르는 함수를 사용해주시면 좋겠죠? 😃

예시

문제 풀이
내 풀이 : 정답 o
select serverno,
DATE_FORMAT(first_login_date, '%Y-%m') AS MONTH,
count(distinct game_account_id) AS cnt_acc
from marketer_sql_users
group by serverno, DATE_FORMAT(first_login_date, '%Y-%m');

  1. 먼저 셀렉트에 문제에서 도출하라는 값 적어줌
    serverno, first_login_date, game_account_id
    from marketer_sql_users 까지
  2. 그 다음 조건인 월 형태 다듬기 dateformat(행, '%y%m')
    여기서 대문자Y를 써야 2015 형태가 됨 소문자 쓰면 15형태
    그리고 따음표를 꼭 써야 인식됨 안쓰면 오류
  3. 그 다음 조건인 서버별, 달별 계정갯수를 세라
    먼저 group by serverno를 하면 전체 갯수를 새던게 서버별로 분할 됨
    그 다음 date~구절을 쓰면 서버별을 기준으로 다시 월로나눔

여기서 중요한 점은 순서를 바꿔서 월별,서버별 로 설정하면 결과값이 뒤틀림

이유는 월별로나누고 거기서 다시 서버별로 나누기때문에

문제2

조건1) group by 를 활용하여 첫 접속일자별 게임캐릭터수를 중복값 없이 구하고,
조건2) having 절을 사용하여 그 값이 10개를 초과하는 경우의 첫 접속일자 및 게임캐릭터id 개수를 추출해주세요.

예시

내 정답 및 문제풀이
select first_login_date,
count(DISTINCT game_actor_id) as cnt_actor
from marketer_sql_users
group by first_login_date
having cnt_actor >10;

  1. 먼저 도출해야되는 값 구함
    first_login_date,
    count(DISTINCT game_actor_id) as cnt_actor
  2. 그룹바이로 "접속일자 별" 임으로 group by first_login_date
    3.having 절은 group by 절 다음 그러니까 집계 후 값에 조건을 걸때 쓰니까(where은 집계전에 사용함 으로 다름 순서도 group by절 위에 씀)
  3. having cnt_actor >10; 의 뜻은 select에 로그인 날짜, 중복안된 계정숫자를 10개 이상인 것만 보여줘 라는 뜻.

문제3

#조건1) group by 절을 사용하여 서버별, 유저구분(기존/신규) 게임캐릭터id수를 구해주세요. 중복값을 허용하지 않는 고유한 갯수로 추출해주세요.
#조건2) 기존/신규 기준→ 첫 접속일자가 2024-01-01 보다 작으면(미만) 기존유저, 그렇지 않은 경우 신규유저
#조건3) 또한, 서버별 평균레벨을 함께 추출해주세요.

정답 !
select serverno,
CASE
WHEN first_login_date < '2024-01-01' THEN '기존유저'
WHEN first_login_date >='2024-01-01' THEN '신규유저'
end as gb,
count(DISTINCT game_actor_id) as actor_cnt,
avg(level) as avg_level
from marketer_sql_users
group by serverno,gb;

  1. 조건 1에 따라 그리고 예시사진 순서에따라 쿼리를 짜준다
    그 과정에서 case when then end 구문이 필요한대 그 이유는 조건 2 때문
  2. 조건 2에따라 작성 하고 그 중에서 두번째 >='2024-01-01' 은 2024-01-01 당일이 포함 안되면 안되기 때문에 써준다 기존유저는 미만이라 상관없음
  3. select 구문을 해석하면 서버 보여줘, 그리고 정해진 기준에따라 기존 유저 신규유저 나눠주고 중복없이 개임 캐릭터 세줘 (레벨평균은 조건3)
  4. 그다음 그룹바이로 서버별, gb 그러니까 기존/신규 유저에따라 캐릭터를 나눈다.
    )1. 서버별로 먼저 나누고 2). 그다음 기존/ 신규 별로 다시나눔 gb를 안쓰면 서버별로 신규 기존 상관없이 다 나옴
  5. 마지막 조건 3 추가 하면 끝.

4번

  • 🔥**문제4 - SubQuery의 활용**
    #2번 문제를 having 이 아닌 인라인 뷰 subquery 를 사용하여, 추출해주세요.

#조건1) 문제2번을 having 이 아닌 인라인 뷰 서브쿼리를 사용하여 추출해주세요.

#힌트: 인라인 뷰 서브쿼리는 from 절 뒤에 위치하여, 마치 하나의 테이블 같은 역할을 했었습니다!

select *
from(
select first_login_date,
count(distinct game_actor_id) as actor_cnt
from marketer_sql_users
group by first_login_date
) as sub_quary
where actor_cnt > 10
;

서브쿼리문을 원래대로 작성하다가
마지막에 인라인 서브쿼리만
1. select *
from(
서브쿼리
) as 별칭 꼭 붙여주기
where로 호출하기
;

5번 문제

#조건1) 레벨이 30 이상인 캐릭터를 기준으로, 게임계정 별 캐릭터 수를 중복값 없이 추출해주세요.
#조건2) having 구문을 사용하여 캐릭터 수가 2 이상인 게임계정만 추출해주세요.
#조건3) 인라인 뷰 서브쿼리를 활용하여 캐릭터 수 별 게임계정 개수를 중복값 없이 추출해주세요.

1번
select game_account_id,
count(DISTINCT game_actor_id)
from marketer_sql_users
where level>=30
2번
select count(DISTINCT game_actor_id),
game_account_id
from marketer_sql_users
where level>=30
group by game_account_id
having count(DISTINCT game_actor_id)>=2

  1. 웨어절을 이용 그룹바이는 저런 트루펄스값 도출 x, 그리고 그룹바이에는 셀렉트에 있는 컬럼이 나와야 함으로
  2. 웨어절에 레벨 조건
  3. 그룹바이로 계정별 조건
  4. 해빙으로 2개이상 새주기 (집계함수 조건)

3번 인라인 쿼리만들기
select a.actor_cnt, count(accnt)
from (
select count(DISTINCT game_actor_id) as actor_cnt ,
game_account_id as accnt
from marketer_sql_users msu
where level>=30
group by game_account_id
having count(DISTINCT game_actor_id) >=2
) as a
group by a.actor_cnt;

  1. 핵심은 본문 셀렉트에서 단축어로 호출하기
  2. 그룹바이에서 게임캐릭터수별로 묶어주기
profile
어디까지 성장할 것 인가..!

0개의 댓글