@@ -2,13 +2,15 @@ import logger from '@/configs/logger.config';
22import { Pool } from 'pg' ;
33import { DBError } from '@/exception' ;
44import { UserLeaderboardSortType , PostLeaderboardSortType } from '@/types/index' ;
5+ import { getCurrentKSTDateString , getKSTDateStringWithOffset } from '@/utils/date.util' ;
56
67export class LeaderboardRepository {
78 constructor ( private pool : Pool ) { }
89
910 async getUserLeaderboard ( sort : UserLeaderboardSortType , dateRange : number , limit : number ) {
1011 try {
11- const cteQuery = this . buildLeaderboardCteQuery ( ) ;
12+ const pastDateKST = getKSTDateStringWithOffset ( - dateRange * 24 * 60 ) ;
13+ const cteQuery = this . buildLeaderboardCteQuery ( dateRange ) ;
1214
1315 const query = `
1416 ${ cteQuery }
@@ -20,17 +22,17 @@ export class LeaderboardRepository {
2022 COUNT(DISTINCT CASE WHEN p.is_active = true THEN p.id END) AS total_posts,
2123 SUM(COALESCE(ts.today_view, 0) - COALESCE(ss.start_view, COALESCE(ts.today_view, 0))) AS view_diff,
2224 SUM(COALESCE(ts.today_like, 0) - COALESCE(ss.start_like, COALESCE(ts.today_like, 0))) AS like_diff,
23- COUNT(DISTINCT CASE WHEN p.released_at >= CURRENT_DATE - make_interval(days := $1::int) AND p.is_active = true THEN p.id END) AS post_diff
25+ COUNT(DISTINCT CASE WHEN p.released_at >= ' ${ pastDateKST } ' AND p.is_active = true THEN p.id END) AS post_diff
2426 FROM users_user u
2527 LEFT JOIN posts_post p ON p.user_id = u.id
2628 LEFT JOIN today_stats ts ON ts.post_id = p.id
2729 LEFT JOIN start_stats ss ON ss.post_id = p.id
2830 WHERE u.email IS NOT NULL
2931 GROUP BY u.id, u.email
3032 ORDER BY ${ this . SORT_COL_MAPPING [ sort ] } DESC, u.id
31- LIMIT $2 ;
33+ LIMIT $1 ;
3234 ` ;
33- const result = await this . pool . query ( query , [ dateRange , limit ] ) ;
35+ const result = await this . pool . query ( query , [ limit ] ) ;
3436
3537 return result . rows ;
3638 } catch ( error ) {
@@ -41,7 +43,7 @@ export class LeaderboardRepository {
4143
4244 async getPostLeaderboard ( sort : PostLeaderboardSortType , dateRange : number , limit : number ) {
4345 try {
44- const cteQuery = this . buildLeaderboardCteQuery ( ) ;
46+ const cteQuery = this . buildLeaderboardCteQuery ( dateRange ) ;
4547
4648 const query = `
4749 ${ cteQuery }
@@ -59,9 +61,9 @@ export class LeaderboardRepository {
5961 LEFT JOIN start_stats ss ON ss.post_id = p.id
6062 WHERE p.is_active = true
6163 ORDER BY ${ this . SORT_COL_MAPPING [ sort ] } DESC, p.id
62- LIMIT $2 ;
64+ LIMIT $1 ;
6365 ` ;
64- const result = await this . pool . query ( query , [ dateRange , limit ] ) ;
66+ const result = await this . pool . query ( query , [ limit ] ) ;
6567
6668 return result . rows ;
6769 } catch ( error ) {
@@ -71,7 +73,11 @@ export class LeaderboardRepository {
7173 }
7274
7375 // 오늘 날짜와 기준 날짜의 통계를 가져오는 CTE(임시 결과 집합) 쿼리 빌드
74- private buildLeaderboardCteQuery ( ) {
76+ private buildLeaderboardCteQuery ( dateRange : number ) {
77+ const nowDateKST = getCurrentKSTDateString ( ) ;
78+ // 과거 날짜 계산 (dateRange일 전)
79+ const pastDateKST = getKSTDateStringWithOffset ( - dateRange * 24 * 60 ) ;
80+
7581 return `
7682 WITH
7783 today_stats AS (
@@ -80,7 +86,7 @@ export class LeaderboardRepository {
8086 daily_view_count AS today_view,
8187 daily_like_count AS today_like
8288 FROM posts_postdailystatistics
83- WHERE ( date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date <= (NOW() AT TIME ZONE 'UTC')::date
89+ WHERE date <= ' ${ nowDateKST } '
8490 ORDER BY post_id, date DESC
8591 ),
8692 start_stats AS (
@@ -89,7 +95,7 @@ export class LeaderboardRepository {
8995 daily_view_count AS start_view,
9096 daily_like_count AS start_like
9197 FROM posts_postdailystatistics
92- WHERE ( date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date >= ((NOW() AT TIME ZONE 'UTC')::date - make_interval(days := $1::int))
98+ WHERE date >= ' ${ pastDateKST } '
9399 ORDER BY post_id, date ASC
94100 )
95101 ` ;
0 commit comments