[내배캠] 데이터분석 6기/본캠프 기록

[본캠프 1일차] SQL 코드카타, SQLD 공부, 직무 스터디

물맨두 2025. 2. 17. 19:49
6월 26일까지 129일 남았다
사전캠프 기간의 5배.. 할 수 있다...!

 

오늘은 본캠프 시작일이다. OT를 듣는데 가장 많이 든 생각은,

'힘들겠구나..' 하는 생각이었다. 컴퓨터 앞에서 공부하면서 밥을요…?

하 그래도 어쩌겠나 우선 해보는 수밖에 없다. 본캠프도 새로이 시작했고, 조원들도 새로이 만나서 이래저래 정신없는 하루였지만 나는 우선 사전캠프부터 공부해오던 게 있으니 그에 따라서 공부와 과제를 해나가기로 했다.

 

오늘 한 일은, 

  • 파이썬 공부
    • [코드카타] 파이썬 문제 1번 풀기
  • SQL 공부
    • [코드카타] SQL 문제 LV.1(1~10번) 풀기
    • [SQLD 자격증 챌린지] 14주차 강의 마저 듣기
  • 직무 스터디 
    • 직무 조사: CRM 마케터

 


 

SQL 공부 ①: SQL 코드카타

매일 오전 루틴으로 코드카타를 푸는 시간을 갖는데 SQL문제가 총 183문제, 파이썬 문제가 총 218문제 있다. 

권장 목표로는 하루에 SQL 1문제, 파이썬 1문제를 푸는 것이다.

 

그런데 사전캠프 기간 동안 개인퀘스트를 풀어보니,

  • 뒤로 갈수록 문제의 난이도가 올라가면서 문제를 푸는 데 들어가는 시간이 갈수록 더 소요됐다는 점
  • 캠프 기간이 진행될수록 배워야 할 내용이 더 추가된다는 점
  • 캠프 기간이 진행될수록 팀 프로젝트에 할애할 시간이 더 필요할 것 같다는 점 등

여러 고민들에 의해 '지금이 가장 널널한 시간이지 않을까' 싶어서 비교적 시간에 여유가 있을 때 쉬운 문제들은 빨리빨리 쳐내는 게 좋을 것 같다는 생각이 들었다. 

그래서 오늘은 SQL문제를 좀 풀어보니 level 1에 해당되는 문제들은 금방 풀 수 있을 것 같아서 SQL 문제를 10번까지 풀고 파이썬 문제도 1번  풀었다. (사실 파이썬 문제는 나중에 확인해서 내일 좀 더 많이 풀기로 했다는 건 안 비밀. 내일 파이썬 문제 level 1까지 풀 계획)

 

오늘 푼 문제 중 다른 문제보다 상대적으로 시간이 많이 걸렸던 문제(사실 별 차이 없긴 함)인 6번과 8번만 어떻게 쿼리를 작성했는지 기록한다.

 

006. 동명 동물 수 찾기

Q. 주어진 테이블을 이용하여 동물 보호소에 들어온 동물의 이름 중 2번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회하기 (단, 결과 테이블에 이름이 없는 동물은 집계에서 제외하고 이름 순으로 정렬하기)

SELECT NAME,
       COUNT(NAME) COUNT
FROM ANIMAL_INS
GROUP BY NAME
HAVING COUNT(NAME) >= 2
ORDER BY NAME;

처음에는 조건 'COUNT(NAME) >= 2'를 WHERE절에 적었다가 에러 메시지를 만났다.

이내 '아차차' 정신을 차려서 HAVING절에 조건을 작성해주었다.

 

그리고 이름 순 정렬을 위해 ORDER BY절을 사용했다.

 

008. 상위 n개 레코드

Q. 동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하기

SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME LIMIT 1;

처음에 컬럼 DATETIME에 MIN() 함수를 사용했나 했더니 에러 메시지를 만났다.

 

그리고서 위와 같이 컬럼 DATETIME을 오름차순으로 정렬하고 그 중 첫 번째 행만 조회하도록 쿼리를 작성했다.

(파이썬은 너무 쉬운 걸로 한 문제만 풀어서 뭐라 적기도 민망하다. 내일은 오늘보다 많이 풀어서 공부할 거리를 적을 수 있도록 해야지)


 

SQL 공부 ②: [SQLD 자격증 챌린지] 수강하기

SQLD 제37회 기출 문제 오답노트

앞선 문제들의 오답풀이를 보고 싶다면 : 

 

[사전캠프 16일차] 아티클 스터디⑪, SQL 과제, SQLD 공부

오늘은 사전캠프 마지막 날오늘 한 일은,마지막 아티클 스터디 진행하기SQL 공부개인 퀘스트(달리기반) - [SQL 실전!] Lv7. 예산이 가장 큰 프로젝트는?[SQLD 자격증 챌린지] 모의고사 풀기[SQLD 자격증

maandoo.tistory.com

저번 강의에 이어서 31번 문제 이후의 오답들에 대해서 공부하는 시간을 가졌다.

 

Q32. 다음 주어진 테이블에 대해서 아래의 SQL문을 수행하였을 때 결과 행의 수는?

[TEST32]
COL1     COL2
-------------
10000    'ABC'
10000    NULL
10000    'AbC'
20000    'ABC'

[SQL]
SELECT * FROM TEST32 WHERE (COL1, COL2) IN ((10000,'ABC'));

  • ⑵⭕: WHERE절 조건이 (COL1, COL2) 쌍으로 주어졌으니 주어진 조건이 모두 일치할 때만 조회되니 결과 행의 수는 1건

 

Q33. 다음 중 TEST 사용자가 아래의 작업을 수행할 수 있도록 권한을 부여하는 DCL로 올바른 것은?

UPDATE A_USER SET COL1 = 'TEST' WHERE COL2 = 100;

  • DCL 명령어에는 GRANT(권한을 부여할 때), REVOKE(권한을 회수할 때) 
    • ⑷⭕: GRANT 명령어 : GRANT _(어떤 권한을)_ ON _(어떤 이에게)_ TO _(어떤 테이블에)_

 

Q35. 주어진 ERD에서 오류가 나지 않는 SQL문을 고르시오.

1)
SELECT * FROM 계좌마스터
WHERE 회원번호 = (SELECT DISTINCT 회원번호 FROM 고객);
2)
SELECT * FROM 계좌마스터
WHERE 회원번호 IN (SELECT DISTINCT 회원번호 FROM 고객);
3)
SELECT 회원번호, 종목코드 FROM 일자별주문내역
WHERE 주문일자 EXISTS (SELECT DISTINCT 주문일자 FROM 계좌마스터);
4)
SELECT 회원번호, 종목코드 FROM 일자별주문내역
WHERE 주문일자 ALL (SELECT DISTINCT 주문일자 FROM 계좌마스터);
  • ⑴❌(∵DISTICNT를 해도 서브쿼리에 들어오는 값이 단일 연산이 안 되는 값 여러 개가 들어옴. 그래서 WHERE절이 = 연산자로 성립하지 않으므로 에러가 발생함)
  • ⑵⭕: ⑴번의 SQL에서 =을 'IN'으로 수정한 것인데 IN을 사용하면 여러 개가 와도 상관 없게 되므로 맞는 SQL문이 됨
  • ⑶❌(∵EXISTS는 앞에 '주문일자'라는 컬럼 조건이 없어야 함)
    • EXISTS (서브쿼리)
  • ⑷❌(∵ALL은 비교연산자와 함께 사용해야 함)
    • ex. '>=ALL', '<ALL' 등

 

Q36. 아래의 실행계획을 순서대로 바르게 나열한 것은?

0 -  SELECT ~
1 -  NESTED LOOP JOIN
2 -    NESTED LOOP JOIN
3 -      TABLE ACCESS(FULL)
4 -      TABLE ACCESS(BY INDEX ROWID)
5 -        INDEX(RANGE SCAN)
6 -    TABLE ACCESS(BY INDEX ROWID)
7 -      INDEX(RANGE SCAN)

  • 컴퓨터가 SQL문 읽는 법
    • ①먼저 읽어야 할 문을 찾는다.
    • ②먼저 읽어야 할 문을 찾았으면 해당 문과 그 문장의 들여쓰기가 같은 문을 같이 읽는다.
    • ③그 문장보다 더 들여쓴 것이 있다면 더 들여쓴 문장을 먼저 읽어야 한다.
  • 문제에선,
    • ① TABLE ACCESS ~[3] 를 먼저 찾는다.
    • ② 그리고서 해당 문장보다 들여쓴 문장인 INDEX ~[5]를 먼저 읽고, 
    • ③ 그 위에 TABLE ACCESS (BY INDEX ROWID)를 읽는다 [4]
    • ④ 더 읽을 문장이 없으니 해당 들여쓰기에서 한 단계 나와서 그 위의 NESTED LOOP ~[2]를 읽는다
    • ⑤ ④과 같은 들여쓰기인 [6], [7]번 중에서 더 들여쓴 INDEX(RANGE ~[7]를 읽는다
    • ⑥ 그 다음으로 나와서 TABLE ACCESS ~[6]을 읽고
    • ⑦ 나와서 [1], [0] 순서대로 읽는다
    • ⑶⭕: 3-5-4-2-7-6-1-0

 

Q37. 다음 ERD로 작성한 SQL문에서 오류가 발생하는 것은?

1)
SELECT (SELECT SUM(주문금액) FROM 일자별주문내역)
FROM 고객마스터 GROUP BY 회원번호;
2)
SELECT SUM(일자별주문내역.주문금액)
FROM 일자별주문내역
FULL OUTER JOIN 고객마스터
ON 고객마스터.회원번호 = 일자별주문내역.회원번호
GROUP BY 회원번호;
3)
SELECT SUM(일자별주문내역.주문금액)
FROM 고객마스터, 일자별주문내역
WHERE 고객마스터.회원번호 = 일자별주문내역.회원번호
GROUP BY 회원번호;
4)
SELECT SUM(주문금액)
FROM 일자별주문내역
WHERE EXISTS (SELECT*FROM 고객마스터
              UNION ALL SELECT*FROM 일자별주문내역)
GROUP BY 회원번호;
  • ⑷❌(∵명령어 'UNION ALL' 컬럼이 정확히 일치해야 쓸 수 있으나 고객마스터 테이블과 일자별주문내역은 컬럼 내용이 일치하지 않으므로 에러가 발생함)

 

Q38. 테이블 TEST38에서 UNIQUE INDEX SCAN을 수행할 수 없는 경우는 무엇인가?

1)
SELECT COL1, COL2, COL3
FROM TEST38 WHERE KEY1 = 5 AND KEY2 = 6;
2)
SELECT COL1, COL2, COL3
FROM TEST38 WHERE KEY1 = 1 AND KEY2 = 2;
3)
SELECT COL1, COL2, COL3
FROM TEST38 WHERE (KEY1, KEY2) IN ((1, 2));
4)
SELECT * FROM TEST38 WHERE KEY1 = 1;
  • UNIQUE INDEX SCAN을 수행하려면 주어진 PK속성을 모두 이용해야 하는데 테이블 TEST38에선 KEY1과 KEY2를 모두 사용해야 함
    • ⑷❌(∵KEY1만 사용하므로 UNIQUE INDEX SCAN을 수행할 수 없음)

 

Q40. 주어진 SQL문에서 ORDER BY로 사용할 수 없는 것은?

[SQL]
SELECT JOB, COUNT(*) AS ROWCNT
FROM TEST40 GROUP BY JOB;

  • ⑷❌(∵숫자 3은 SELECT절에 작성한 컬럼 중 세 번째 컬럼을 기준으로 정렬하겠다는 의미인데 SELECT절에 적은 건 2개뿐)

 

Q42. CROSS JOIN과 NATURAL JOIN의 차이점에 대해서 잘못 설명한 것은?

  • ⑶❌(∵CROSS JOIN과 NATURAL JOIN은 JOIN 조건을 걸 필요가 없이 알아서 되나 필터링이 필요한 경우에 WHERE절에 조건을 걸 수도 있음)

 

Q43. 다음 주어진 데이터에 대해서 아래의 계층형 SQL문을 실행하였을 때의 결과값이 아래와 같을 때 계층형 SQL문에서 빈칸에 들어갈 것으로 올바른 것은?

[TEST43]
EMPNO    MGR
-------------
8000     NULL
7788     7566
7566     8000
7876     7788

[SQL]
SELECT LEVEL, LPAD(' ', 4 * (LEVEL-1)) ||
EMPNO EMPLOYEE, MGR MANAGER, 
CONNECT_BY_ISLEAF AS LEAF FROM TEST43
START WITH (  ㄱ  ) 
CONNECT BY PRIOR (  ㄴ  );

[RESULT]

    LEVEL   EMPLOYEE	  MANAGER     LEAF
---------- -------------------- ---------- ----------
	 1         8000 	   0
	 2         7566		   8000	      0
	 3	    7788 	   7566	      0
	 4	    7876	    7788	1

  • ㄱ: MGR이 NULL값인 조건이 적혀 있어야 함
  • ㄴ: EMPNO와 MGR 값이 같아야 한다는 조건이 필요
  • => ⑷⭕

 

Q44. 다음 주어진 두 개의 테이블에 대해서 아래와 같은 결과값이 반환되도록 아래의 SQL문의 빈칸에 들어갈 값으로 올바른 것은?

[TEST44_1]
STUDENTNO
---------
10
20
30

[TEST44_2]
GRADE
---------
50
60
70
[결과값]
     GRADE  STUDENTNO SUM(B.GRADE)
---------- ---------- ------------
	50	   10		50
	50	   20		50
	50	   30		50
	50		       150
	60	   10		60
	60	   20		60
	60	   30		60
	60		       180
	70	   10		70
	70	   20		70
	70	   30		70
	70		       210


[SQL]
SELECT B.GRADE, A.STUDENTNO, SUM(B.GRADE)
FROM TEST44_1 A, TEST44_2 B
GROUP BY (             );

  • SQL문의 FROM절을 보면 암시적 JOIN을 했음을 알 수 있음
    • 단, 암시적 JOIN의 경우에 동일한 컬럼이 없다면 CROSS JOIN으로 수행함
    • 그래서 그를 막기 위해 GROUP BY절에 GROUPING SETS() 함수가 필요
      • 첫 번째 컬럼으로 온 GRADE 컬럼을 먼저 적고
      • 그 다음에 (STUDENTNO, GRADE)를 이렇게 괄호 속에 넣어서 적어줘야 함
      • => ⑴GROUPING SETS(B.GRADE, (B.GRADE, A.STUDENTNO))⭕

 

Q45. Oracle 환경에서 주어진 테이블을 아래의 결과와 같이 정렬하고자 할 때, SQL문의 빈칸에 들어갈 값으로 올바른 것은?

[TEST45]
C1    C2
----------
10    100
10    200
10    NULL
20    100
20    NULL
20    200

[RESULT]
C1    C2
----------
10    200
10    100
10    NULL
20    200
20    100
20    NULL

[SQL]
SELECT C1, C2
FROM SQLD_02
ORDER BY C1, C2 DESC (      );

  • 정렬 시 NULL값의 순서를 정하는 명령어는 NULLS~
  • ⑵⭕(∵내림차순 정렬로 했으니 NULLS LAST일 때 결과 테이블에 조회된 대로 NULL값을 마지막에 정렬시킴)

 

Q49. 주어진 데이터에 대해서 아래의 SQL문을 수행하였을 때의 결과값이 아래의 결과와 같을 때 빈칸에 들어갈 값을 적으시오

[TEST49]
CREATE TABLE TEST49(
COL1 VARCHAR(10),
COL2 VARCHAR(10),
COL3 NUMBER(10)
);
INSERT INTO TEST49 VALUES('A','가',10);
INSERT INTO TEST49 VALUES('A','가',20);
INSERT INTO TEST49 VALUES('A','다',25);
INSERT INTO TEST49 VALUES('B','가',10);
INSERT INTO TEST49 VALUES('B','나',30);
INSERT INTO TEST49 VALUES('B','나',20);
INSERT INTO TEST49 VALUES('B','나',60);
INSERT INTO TEST49 VALUES('C','라',30);
[SQL]
SELECT NTILE_2, COUNT(*) AS ROWCNT
FROM (
      SELECT COL1, COL2, COL3, NTILE(3) OVER(ORDER BY COL3) AS NTILE_2
      FROM TEST49
      )
GROUP BY NTILE_2;
[RESULT]
NTILE_2   ROWCNT
----------------
1          3
2          3
(   )      (   )

  • NTILE(n) OVER(): n등급 연산을 하는 함수
    • NTILE(3) OVER(ORDER BY COL3) : COL3를 기준으로 오름차순 정렬하여 3등급으로 나눌 것
    • COL3 오름차순 정렬: 10 10 20 20 25 30 30 60
    • 이를 3등급으로 나눌 것: 10 10 20 / 20 25 30 / 30 60
  • ⑷⭕: 위의 연산에 따라서 3등급에 해당하는 값은 ROWCNT가 2건

 


 

직무 스터디: CRM 마케터

CRM 마케팅이란?

  • CRM : Customer Relationship Management의 약자로, 고객과의 관계를 관리하는 것을 의미
  • CRM 마케팅 : 고객이 자사 플랫폼(서비스)에 유입됐을 때, 말을 걸고 구매를 유도하고 구매한 이후 재탐색을 유도하는 등 리텐션을 높이는 모든 고객 대상 마케팅을 의미

 

주요 업무

  • 사용자 여정별로 누구에게, 언제, 어떤 메시지로 대화를 걸지 등 촘촘한 CRM 시나리오 설계를 주로 함
  • CRM 시나리오 설계를 구현하기 위해 다양한 툴(braze, amplitude, SQL, 태블로 등)을 활용해 CRM 마케팅 진행

 

필요 역량

  • 프로젝트의 목적과 정량화된 목표, 그리고 문제를 정의할 수 있어야 함 (기본)
    • 고객이 서비스 이용 중 가지고 있는 문제 중 무엇을 해결하고자 하는 것인지 생각할 줄 알아야 함
  • 사용자 행동에 따른 마케팅 캠페인 설계 역량, 데이터 택소노미 설계 역량(①), 데이터 분석 역량(②), CRM 마케팅 툴 활용 역량(③)
    • 데이터 택소노미(Data Taxonomy)
      : 마케팅 관점에서 데이터를 그룹화 하고 구성하는 방법. 프로덕트를 연동할 때 사용자가 취하는 액션 로그가 남는데 이것을 '이벤트'라 하고 이 이벤트를 추적하기 위해 이름을 붙여주는 방식을 '데이터 택소노미'라 함.
    • 데이터 분석 역량 : 태블로, 엑셀, SQL 등
    • CRM 마케팅 툴 : Braze 등

 

채용 공고 (업무 내용과 자격 요건 등에서 필요 역량을 맞춰보는 방식으로)

 

  • 1️⃣
    • Funnel 분석을 사용하여 마케팅 전략을 세울 줄 아는가
    • 적절한 이벤트 택소노미를 정의할 수 있는가
    • 고객 세그먼트를 세분화하여 각각에 맞는 캠페인을 기획하고 운영할 줄 아는가

 

  • 2️⃣
    • 해당 공고는 CRM 마케터가 아닌 '데이터 분석가(그로스해커)' 공고라 적혀 있지만 해당 기업에선 그로스해킹팀에서 CRM을 담당하고 있음을 공고에서 확인할 수 있음
      • CRM 마케터라 제목에 내걸지 않은 공고라도 업무 내용을 확인해야 할 필요가 있음
    • 문제 정의 - 가설 설정 - 실험 설계 - 결과의 과정에 따라서 프로젝트 경험이 있는지 (기본)
    • 데이터를 추출하고 분석해 본 경험이 있는지 (있다면 구체적인 설명과 자료를 첨부한 포트폴리오 및 경력기술서 제출)
    • 고객 세그먼트별 마케팅 전략 수립
    • AARRR 모델, 퍼널 분석, 코호트 분석 등 그로스 해킹 지표와 분석 방법에 이해가 있는지 
    • SQL과 Python을 다룰 수 있는지

 

  • 3️⃣
    • CRM 채널 및 캠페인을 기획하고 운영 (카카오톡, 앱푸시, 문자, 이메일 등)
    • 고객 행동 패턴 분석에 따른 적절한 CRM 액션 설계
    • 고객 데이터와 마케팅 성과 추적 및 분석/리뷰 ①+②
    • 데이터 분석 역량 : SQL, Amplitude 등
    • CRM 마케팅 툴 사용 역량 : Braze, 카카오모먼트 등

 


 

오늘은 사실 첫 날이라 어떻게 흘러갔는지 모르겠다.

한 일주일은 이대로 살아봐야 '본캠프가 이런 거구나' 하는 감과 나만의 루틴이 생길 듯하다.

 

그래도 오늘 정도면 괜찮게 첫 날 시작한 거 같아서 기분은 좋다!

 

우선 내일부터 팀별 아티클 스터디를 진행하고,

250217 코드카타 문제 레벨별로 나눠보았다

또 코드카타 문제를 SQL은 Level 1에 해당하는 문제를 다 끝내서 내일부턴 하루에 하나씩 풀고, 파이썬은 30번까지가 Level 1에 해당하므로 하루에 10문제씩 풀면 이번 주는 괜찮을 것 같다.