식당 고객들의 방문 기록과 결제 금액이 담긴 테이블이 있다.
각 날짜를 기준으로 그 날짜를 포함한 직전 6일까지의 7일간 매출을 기준으로,
WITH A AS (
SELECT visited_on, SUM(amount) AS amount
FROM Customer
GROUP BY visited_on
)
SELECT
a1.visited_on,
SUM(a2.amount) AS amount,
ROUND(SUM(a2.amount) / 7, 2) AS average_amount
FROM A a1
JOIN A a2
ON a2.visited_on BETWEEN DATE_SUB(a1.visited_on, INTERVAL 6 DAY) AND a1.visited_on
GROUP BY a1.visited_on
HAVING COUNT(*) = 7
ORDER BY a1.visited_on;
WITH A
: 날짜별 매출 합계를 먼저 구해서 하루당 1개의 행으로 정리함a1
은 기준 날짜, a2
는 그 기준 날짜로부터 최근 7일간의 데이터JOIN
은 a2.visited_on BETWEEN a1.visited_on - 6일 AND a1.visited_on
으로 슬라이딩 윈도우 구성SUM(a2.amount)
으로 7일간 총 매출을 구하고, ROUND(... / 7, 2)
로 평균 매출 계산HAVING COUNT(*) = 7
조건으로 정확히 7일치가 존재할 때만 출력ORDER BY a1.visited_on
으로 날짜 오름차순 정렬문제:
최대공약수와 최소공배수
문제설명:
두 수 n, m을 입력받아
[GCD, LCM]
형태로 반환하는 함수 만들기.(n * m) // GCD
공식 사용.내 정답:
def solution(n, m):
answer = []
def gcd(a, b):
while b:
a, b = b, a % b
return a
g = gcd(n, m)
l = (n * m) // g
answer = [g, l]
return answer
정답 쿼리 설명:
gcd(a, b)
함수는 유클리드 호제법으로 최대공약수를 구함. a, b = b, a % b
를 계속하면서 b == 0
이 될 때까지 반복 a
가 최대공약수(n * m) // g
공식으로 계산[g, l]
형식으로 리스트에 담아 리턴unique_logins
, employee_count
SELECT unique_logins, COUNT(*) AS employee_count
FROM (
SELECT e.employee_id, COUNT(*) AS unique_logins
FROM logins l
INNER JOIN employees e ON l.employee_id = e.employee_id
WHERE DATE(l.login_time) BETWEEN '2023-07-01' AND '2023-09-30'
AND l.login_result = 'SUCCESS'
GROUP BY e.employee_id
) a
GROUP BY unique_logins
ORDER BY unique_logins;
SUCCESS
로그인만 집계DATE()
함수로 필터링 (날짜 범위 정확하게 계산)COUNT(*)
)GROUP BY unique_logins
을 통해 각 그룹별 인원수를 셈ORDER BY
로 로그인 횟수 기준 정렬employee_id
, name
, salary
WITH ranked_salaries AS (
SELECT
employee_id,
name,
salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee_salary
)
SELECT employee_id, name, salary
FROM ranked_salaries
WHERE rnk = 3
ORDER BY employee_id;
DENSE_RANK()
윈도우 함수를 사용해 급여 내림차순 순위를 부여WITH
절(CTE)로 먼저 순위를 구한 다음rnk = 3
만 필터링ORDER BY employee_id
로 정렬inter_department_msg_pct
SELECT
ROUND(
(SUM(CASE WHEN E.department != P.department THEN 1 ELSE 0 END) / COUNT(*)) * 100,
1
) AS inter_department_msg_pct
FROM messages M
JOIN employees E ON M.sender_id = E.employee_id
JOIN employees P ON M.receiver_id = P.employee_id
WHERE E.department IS NOT NULL AND P.department IS NOT NULL;
messages
테이블의 송신자와 수신자를 employees
와 각각 조인department IS NOT NULL
조건으로 유효한 메시지만 필터링CASE WHEN
을 이용해 서로 다른 부서이면 1, 같으면 0으로 처리해 합산ROUND(..., 1)
로 소수 첫째 자리까지 반올림converted = 1
인 세션을 가진 유저만 분석 대상created_at
이 가장 이른 세션을 찾음user_id
, channel
SELECT user_id, channel
FROM (
SELECT
u.user_id,
a.channel,
RANK() OVER (PARTITION BY u.user_id ORDER BY u.created_at) AS r
FROM user_sessions u
JOIN ad_attribution a ON u.session_id = a.session_id
WHERE u.user_id IN (
SELECT u2.user_id
FROM user_sessions u2
JOIN ad_attribution a2 ON u2.session_id = a2.session_id
WHERE a2.converted = 1
)
) a
WHERE r = 1
ORDER BY user_id;
converted = 1
조건을 만족하는 유저만 서브쿼리로 추출RANK()
윈도우 함수로 각 유저의 created_at
기준으로 세션 순위 부여user_id
기준 오름차순 정렬