TIL - 유량(Flow)과 저량(Stock) 계산하기
문제 설명
MoMA 미술관의 작품 데이터를 이용하여 연도별 작품 수를 분석하는 문제였다.
문제에서는 두 가지 지표를 구해야 했다.
첫 번째는 유량(Flow) 이다.
유량 : 일정 기간 동안 새롭게 발생한 양
예를 들면
- 연도별 신규 가입자 수
- 월별 주문 건수
- 연도별 신규 소장 작품 수
같은 개념이다.
두 번째는 저량(Stock) 이다.
저량 : 특정 시점까지 누적되어 있는 총량
예를 들면
- 누적 회원 수
- 누적 주문 수
- 누적 소장 작품 수
같은 개념이다.
이번 문제에서는
Acquisition year
New acquisitions this year (Flow)
Total collection size (Stock)
를 출력해야 했다.
또한
- acquisition_date가 NULL인 작품 제외
- 연도 기준 오름차순 정렬
조건이 있었다.
내가 처음 생각한 접근
처음에는
COUNT(*) OVER(...)
와
SUM(...) OVER(...)
를 사용해서 바로 Flow와 Stock을 만들려고 했다.
생각한 흐름은
작품 데이터
↓
윈도우 함수
↓
Flow 생성
↓
Stock 생성
이었다.
Flow와 Stock 둘 다 집계 문제라고 생각했기 때문에 자연스럽게 윈도우 함수를 먼저 떠올렸다.
내가 헷갈렸던 부분
이번 문제에서 가장 헷갈렸던 부분은
Flow와 Stock의 관계를 제대로 이해하지 못했던 것이었다.
처음에는
Flow와 Stock을 각각 따로 계산해야 한다
고 생각했다.
하지만 실제로는
Flow를 먼저 만든 뒤
↓
Flow를 누적하면
↓
Stock이 된다
는 구조였다.
또 하나 실수했던 부분은
SUM(artwork_id)
같은 형태로 Stock을 계산하려고 생각한 점이다.
하지만 Stock은
작품 ID의 합
이 아니라
작품 수의 누적합
이다.
예를 들어
2014 : 10개
2015 : 5개
2016 : 8개
라면
Flow는
2014 : 10
2015 : 5
2016 : 8
이고
Stock은
2014 : 10
2015 : 15
2016 : 23
가 된다.
즉
Stock = Flow의 누적합
이라는 사실을 이해해야 했다.
최종 해결 방법
이번 문제는 두 단계로 나누어 생각해야 했다.
1단계. 연도별 작품 수 계산
먼저 연도별 작품 수를 집계한다.
이 값이 바로 Flow이다.
즉
2014 → 10
2015 → 5
2016 → 8
같은 결과를 만드는 단계이다.
2단계. Flow 누적합 계산
이후
SUM(cnt) OVER(ORDER BY year)
를 사용해 누적합을 계산한다.
그러면
10
10 + 5
10 + 5 + 8
이 계산된다.
이 값이 바로 Stock이다.
여기서 중요한 점은
Flow를 먼저 만들고 -> Stock을 만든다
는 사고 순서이다.
정답 쿼리
WITH a AS (
SELECT
DATE_FORMAT(acquisition_date,'%Y') AS a_year,
COUNT(*) AS cnt
FROM artworks
WHERE acquisition_date IS NOT NULL
GROUP BY a_year
)
SELECT
a_year AS 'Acquisition year',
cnt AS 'New acquisitions this year (Flow)',
SUM(cnt) OVER(
ORDER BY a_year
) AS 'Total collection size (Stock)'
FROM a
ORDER BY a_year;
이번 문제에서 배운 패턴
원본 데이터
↓
기간별 집계
↓
Flow 생성
↓
SUM() OVER()
↓
누적합 계산
↓
Stock 생성
한 줄 요약
Flow와 Stock 문제는 "먼저 기간별 집계로 Flow를 만들고, 그 Flow를 누적합하여 Stock을 계산한다"는 패턴으로 해결한다.
'TIL' 카테고리의 다른 글
| [TIL169] HackerRank - Type of Triangle (0) | 2026.06.24 |
|---|---|
| [TIL168] solvesql - 세 명의 사용자가 서로 친구인 관계 찾기 (Triangle 관계 탐색) (0) | 2026.06.23 |
| [TIL166] solvesql - Facebook 친구 수 집계하기 (0) | 2026.06.23 |
| [TIL165] solvesql - 세션 유지시간 10분으로 재정의하기(max) (0) | 2026.06.23 |
| [TIL164] solvesql - 미세먼지 수치의 계절별 pm10 중앙값, 평균값 (0) | 2026.06.22 |