날짜랑 시간은 그냥 추상적인 숫자가 아니라, 데이터에서 진짜 중요한 정보를 담고 있어. 실제로 살다 보면 날짜를 자주 만나게 돼: 예를 들어, 월별 매출 분석, 직원 생일로 필터링, 시간 간격 비교 등등. 날짜를 잘 다루면 훨씬 유연하게 쿼리 짤 수 있고, 복잡한 분석도 할 수 있어.
날짜가 진짜 중요한 예시들:
- 특정 달의 매출 분석.
- 지난 1년 동안 가입한 사용자 수 세기.
- 시간 간격별 리포트 만들기 (예: 월별 수익).
PostgreSQL에는 날짜 다루는 함수가 엄청 많아. 지금은 그중에서 제일 유용한 것들만 볼 거야.
날짜와 시간 다루는 기본 함수들
NOW() 함수는 데이터베이스 서버의 현재 날짜와 시간을 돌려줘. 지금 정확한 시간이 필요할 때 쓰면 돼. 예를 들어, 새 레코드 만들 때 생성 시간을 기록하고 싶을 때 쓸 수 있지.
SELECT NOW();
예시 결과:
2023-11-05 15:23:45.123456+00
사용 예시: 주문을 현재 날짜와 시간으로 기록하고 싶을 때:
INSERT INTO orders (order_id, order_date, total_amount)
VALUES (1, NOW(), 150.00);
코멘트: 여기서
NOW()가 자동으로 현재 날짜와 시간을
order_date 컬럼에 넣어줄 거야.
INSERT 연산자가 어떻게 동작하는지는 다음 강의에서 알려줄게 :P
CURRENT_DATE 함수
시간은 필요 없고 날짜만 넣고 싶으면 CURRENT_DATE를 써. 이건 연, 월, 일만 돌려줘.
문법:
SELECT CURRENT_DATE;
예시 결과:
2023-11-05
사용 예시: 오늘 날짜의 레코드만 가져오고 싶을 때:
SELECT *
FROM orders
WHERE order_date = CURRENT_DATE;
코멘트: 여기서는
order_date 컬럼의 날짜랑 오늘 날짜를 비교하는 거야.
조금 웃긴 비유 하나. NOW()는 회사에서 마시는 커피 같아: 바로 지금을 위한 거지. CURRENT_DATE는 벽에 붙은 달력 같아: 날짜만 있고, 쓸데없는 정보는 없어.
DATE_PART()로 날짜 일부 추출하기
DATE_PART() 함수는 날짜에서 연, 월, 일, 시, 분 같은 특정 부분만 뽑아낼 수 있어. 예를 들어, 특정 연도의 주문 수를 세거나, 요일을 알아낼 때 유용하지.
문법:
DATE_PART('부분', 날짜)
예시:
SELECT DATE_PART('year', NOW()) AS current_year;
예시 결과:
| current_year |
|---|
| 2025 |
추출할 수 있는 날짜 부분들:
year: 연도.month: 월.day: 일.hour: 시.minute: 분.second: 초.dow: 요일 (0 = 일요일).
예시 2: 현재 날짜에서 월 추출하기.
SELECT DATE_PART('month', CURRENT_DATE) AS current_month;
결과:
| current_month |
|---|
| 6 |
DATE_PART()는 복잡한 계산에도 쓸 수 있어. 예를 들어:
올해 태어난 학생만 뽑고 싶을 때:
SELECT *
FROM students
WHERE DATE_PART('year', birth_date) = DATE_PART('year', CURRENT_DATE);
예시 결과:
| id | first_name | last_name | birth_date | grade |
|---|---|---|---|---|
| 1 | Otto | Art | 2025-03-12 | 9 |
| 2 | Anna | Pal | 2025-07-08 | 8 |
| 3 | Piu | Wolf | 2025-01-22 | 10 |
| 4 | Eva | Go | 2025-09-30 | 7 |
| 5 | Dan | Sok | 2025-06-14 | 9 |
실전 예제
몇몇 예제에서는 아직 안 배운 연산자도 나올 거야. 걱정하지 마, 곧 이런 예제도 껌처럼 풀 수 있을 거야. 그냥 실제로 어떻게 쓰이는지 많이 보여주고 싶어서야. 그리고 살짝 궁금증도 주고 ㅎㅎ :)
예시 1: 사용자 나이 구하기
예를 들어, users 테이블에 각 사용자의 생일이 있다고 해보자. 나이를 계산하고 싶어.
쿼리:
SELECT user_id, first_name, last_name,
DATE_PART('year', CURRENT_DATE) - DATE_PART('year', birth_date) AS age
FROM users;
그냥 현재 연도에서 생일 연도를 빼는 거야. 빠르긴 한데, 완전히 정확한 나이는 아니야.
예시 결과:
| user_id | first_name | last_name | age |
|---|---|---|---|
| 101 | Alex | Lin | 25 |
| 102 | Maria | Chi | 30 |
| 103 | Tor | Coz | 22 |
| 104 | Nat | Ive | 27 |
| 105 | Don | Sok | 35 |
예시 2: 시간으로 필터링하기
마지막 1시간 동안 들어온 주문만 뽑고 싶으면:
SELECT *
FROM orders
WHERE order_date >= NOW() - INTERVAL '1 hour';
INTERVAL (시간 간격 표현) 쓰는 게 얼마나 편한지 봐봐.
예시 3: 월별로 그룹화하기
올해 각 달마다 주문 수를 세고 싶으면:
SELECT DATE_PART('month', order_date) AS order_month, COUNT(*) AS order_count
FROM orders
WHERE DATE_PART('year', order_date) = DATE_PART('year', CURRENT_DATE)
GROUP BY DATE_PART('month', order_date)
ORDER BY order_month;
월 번호로 그룹화하고, 결과도 월 순서대로 정렬해.
예시 결과:
| order_month | order_count |
|---|---|
| 1 | 120 |
| 2 | 95 |
| 3 | 134 |
| 4 | 110 |
| 5 | 42 |
예시 4: 요일 추출하기
어느 요일에 주문이 제일 많은지 알고 싶으면:
SELECT DATE_PART('dow', order_date) AS day_of_week, COUNT(*) AS order_count
FROM orders
GROUP BY DATE_PART('dow', order_date)
ORDER BY order_count DESC;
DATE_PART('dow')는 각 주문의 요일을 숫자로 돌려줘. 0은 일요일, 1은 월요일, 이런 식이야. DOW는 DayOfWeek(요일)의 약자야.
예시 결과:
| day_of_week | order_count |
|---|---|
| 5 | 210 |
| 4 | 190 |
| 3 | 175 |
| 2 | 160 |
| 1 | 140 |
| 6 | 120 |
| 0 | 95 |
자주 하는 실수들 주의!
날짜 다루다 보면 실수 때문에 머리 아플 때 많아. 자주 나오는 문제 몇 개만 짚어줄게:
시간/날짜 포맷: NOW()나 날짜+시간을 돌려주는 함수 쓸 때는 꼭 포맷을 확인해. 예를 들어, order_date랑 CURRENT_DATE를 비교할 때는 시간 부분이 무시되는지, 아니면 명확하게 지정했는지 체크해야 해.
문자열로 저장된 날짜: DB에 날짜가 문자열(텍스트)로 저장된 경우가 많아. 이럴 때 날짜 함수(DATE_PART() 등) 쓰면 에러 나. 데이터 타입이 DATE나 TIMESTAMP인지 꼭 확인해.
다른 타임존: 서버 타임존이랑 데이터 수집 타임존이 다르면 헷갈릴 수 있어. TIMESTAMPTZ (타임존 포함된 timestamp) 쓰는 것도 고려해봐.
GO TO FULL VERSION