Lv1. 데이터 속 김서방 찾기
문제

본격적으로 시작해 볼까요?
•
상황: 여러분들은 스파르타코딩클럽의 분석가로 취직했습니다. DBeaver를 테스트 해볼 겸 “김”씨로 시작하는 이용자들 수를 세어 보기로 했습니다.
•
데이터 설명
◦
user 테이블은 스파르타 코딩클럽에 가입한 유저들의 정보를 날짜별로 기록한 테이블입니다.
▪
user_id: 익명화된 유저들의 아이디(varchar255)
▪
created_at: 아이디 생성 날짜(timestamp)
▪
updated_at: 정보 업데이트 날짜(timestamp)
▪
name: 익명화된 유저들의 이름(varchar255)
▪
email: 이메일(varchar255)

•
문제: 다음과 같은 결과테이블을 만들어봅시다.
◦
name_cnt: “김”씨 성을 가지고 있는 교육생의 수

name_cnt: “김”씨 성을 가지고 있는 교육생의 수
select COUNT(name)
from users
where name like '김%'
이렇게 풀었는데 결과 값은 정답과 같지만 문제점이 있었다.
****************************************
만약 동일한 user_id가 여러 줄에 걸쳐 등장하거나,
한 사람이 여러 번 등록된 경우에는 틀릴 수 있다.
그래서 실무에서는 항상 DISTINCT + 고유 식별자(user_id) 쓰는 게 더 안전한 습관
+
like(간단한 상황에는 좋음) 보다는 substr을 사용해 찾는게 처리범위도 적어 속도면에서 더 빠를 수 있다.
****************************************
그래서 새로 쓰면
select count(distinct user_id) as name_count
from users
where substr(name,1,1) = '김'
Lv2. 날짜별 획득포인트 조회하기
문제

•
상황: 이번에는 이용자들이 잘 활동하고 있는지 보고자 합니다. 포인트가 많을수록 활동을 잘하고 있다고 생각 할 수 있습니다. 날짜별로 획득한 포인트가 점점 늘어나는지 줄어드는지 확인해 봅시다.
•
데이터 설명
◦
point_users 테이블은 스파르타코딩클럽 가입 유저들의 포인트에 대한 정보를 기록한 테이블입니다.
▪
point_user_id: user_point 행을 구별하기 위한 key(varchar255)
▪
created_at: 아이디 생성 날짜(timestamp)
▪
updated_at: 정보 업데이트 날짜(timestamp)
▪
user_id: 익명화된 유저들의 아이디(varchar255)
▪
point: 보유하고 있는 포인트(int)

•
문제: 다음과 같은 결과테이블을 만들어봅시다.
◦
created_at: 익명화된 유저들의 아이디(varchar255)
◦
average_points: 유저가 획득한 날짜별 평균 포인트(int), 반올림 필수

SELECT date(created_at), round (AVG(point)) as point_avg
from point_users
group by 1
***
DATE 함수를 이용하면 TIMESTAMP 형식의 데이터를 날짜 형태로 변형할 수 있다.
***
Lv3. 이용자의 포인트 조회하기
문제

본격적으로 시작해 볼까요?
•
상황: 이번에는 이용자들 별로 획득한 포인트를 학생들에게 이메일로 보내려고 합니다. 이를 위한 자료를 가공해봅시다. 특히 users 테이블에는 있으나 point_users 에는 없는 유저가 있어요. 이 유저들의 경우 point를 0으로 처리합시다.
•
데이터 설명
◦
users 테이블은 스파르타 코딩클럽에 가입한 유저들의 정보를 날짜별로 기록한 테이블입니다.
▪
user_id: 익명화된 유저들의 아이디(varchar255)
▪
created_at: 아이디 생성 날짜(timestamp)
▪
updated_at: 정보 업데이트 날짜(timestamp)
▪
name: 익명화된 유저들의 이름(varchar255)
▪
email: 이메일(varchar255)

◦
point_users 테이블은 스파르타코딩클럽 가입 유저들의 포인트에 대한 정보를 기록한 테이블입니다.
▪
point_user_id: point_users 테이블의 행을 구별하기 위한 key(varchar255)
▪
created_at: 아이디 생성 날짜(timestamp)
▪
updated_at: 정보 업데이트 날짜(timestamp)
▪
user_id: 익명화된 유저들의 아이디(varchar255)
▪
point: 보유하고 있는 포인트(int)

•
문제: 다음과 같은 결과 테이블을 만들어봅시다.
◦
user_id: 익명화된 유저들의 아이디
◦
email: 유저들의 이메일
◦
point: 유저가 획득한 포인트
▪
users 테이블에는 있지만 point_users에는 없는 user는 포인트가 없으므로 0 으로 처리
▪
포인트 기준으로 내림차순 정렬
◦
1~10행

◦
490 ~ 498행

SELECT u.user_id, u.email, ifnull(p.point,0) as point
from users u
left join point_users p on p.user_id = u.user_id
order by p.point desc
***
처음에 if ( p.point = null, 0, p.point )라고 쿼리를 작성했는데
null 값은 비교 연산자를 사용 x
그래서 if null or coalesce 사용
***
Lv4. 단골 고객님 찾기
문제:
Orders 테이블:
OrderID
|
CustomerID
|
OrderDate
|
TotalAmount
|
101
|
1
|
2024-01-01
|
150
|
102
|
2
|
2024-01-03
|
200
|
103
|
1
|
2024-01-04
|
300
|
104
|
3
|
2024-01-04
|
50
|
105
|
2
|
2024-01-05
|
80
|
106
|
4
|
2024-01-06
|
400
|
Customers 테이블:
CustomerID
|
CustomerName
|
Country
|
1
|
Alice
|
USA
|
2
|
Bob
|
UK
|
3
|
Charlie
|
USA
|
4
|
David
|
Canada
|
요구사항:
1.
고객별로 주문 건수와 총 주문 금액을 조회하는 SQL 쿼리를 작성해주세요.
a.
출력 결과에는 고객 이름, 주문 건수, 총 주문 금액이 포함되어야 합니다. 단, 주문을 한 적이 없는 고객도 결과에 포함되어야 합니다.
b.
기대결과
CustomerName
|
OrderCount
|
TotalSpent
|
Alice
|
2
|
450
|
Bob
|
2
|
280
|
Charlie
|
1
|
50
|
David
|
1
|
400
|
SELECT
c.CustomerName,
count(o.OrderID) as orderCount,
sum(o.TotalAmount) as TotalSpent
from p4_orders_table o
join p4_customers_table c on o.CustomerID = c.CustomerID
group by c.CustomerName
***
처음에 위에 쿼리를 작성
문제에 주문한 적이 없는 고객
조회 -> left join
주문 x -> 즉, null 값일테니 0으로 반환
***
SELECT
c.CustomerName,
count(o.OrderID) as orderCount,
ifnull(sum(o.TotalAmount),0) as TotalSpent
from p4_orders_table o
left join p4_customers_table c on o.CustomerID = c.CustomerID
group by c.CustomerName
2.
나라별로 총 주문 금액이 가장 높은 고객의 이름과 그 고객의 총 주문 금액을 조회하는 SQL 쿼리를 작성해주세요.
a.
기대결과
Country
|
Top_Customer
|
Top_Spent
|
USA
|
Alice
|
450
|
UK
|
Bob
|
280
|
Canada
|
David
|
400
|
제약사항:
•
두 쿼리 모두 서브쿼리, JOIN, GROUP BY, HAVING 등을 사용해 풀 수 있어야 한다.
•
주문을 한 적이 없는 고객도 첫 번째 쿼리 결과에 포함되어야 한다.
SELECT
c.Country, c.CustomerName as Top_customer, sum(o.totalamount) as Total_Spent
from p4_orders_table o
join p4_customers_table c on o.CustomerID = c.CustomerID
group by c.Country,c.CustomerName
Having
sum(o.totalamount) = (
select max(SumSpent)
from (
select sum(o2.totalamount) as SumSpent
from p4_orders_table o2
join p4_customers_table c2 on o2.CustomerID = c2.CustomerID
where c2.Country = c.Country
group by c2.CustomerID
) as t
)
나라별로 총 주문 금액이 가장 높은 고객의 이름과 그 고객의 총 주문 금액을 조회하는 SQL 쿼리를 작성해주세요.
실행 순서 요약
단계설명
① | FROM + JOIN으로 고객별 주문 목록 완성 |
② | GROUP BY로 고객별 합계 계산 |
③ | HAVING절의 서브쿼리가 각 Country마다 실행됨 |
④ | 그 Country 내에서 최고 총합만 남김 (조건 만족한 고객만 남음) |
⑤ | SELECT로 최종 결과 출력 |
HAVING절은 파이썬의 for문과 비슷한 개념으로 생각하니 이해가 간다.
조건을 만들어놓고 나라별로 대입되며 조건에 맞는 값만 필터링한다.