source: db-scripts/p6_q2_annual_training_consistency_workload.sql@ 89156c1

Last change on this file since 89156c1 was 89156c1, checked in by Andrej <asumanovski@…>, 3 months ago

Phase 6 documentation

  • Property mode set to 100644
File size: 3.9 KB
Line 
1SET search_path TO trekr;
2
3-- P6 Q2 (Annual): Training consistency, workload trend, and peak period analysis.
4-- Change report_year in params CTE when needed.
5WITH params AS (
6 SELECT 2026::int AS report_year
7),
8months AS (
9 SELECT generate_series(1, 12) AS month_no
10),
11training_base AS (
12 SELECT
13 tu.user_id,
14 u.username,
15 u.email,
16 tu.gender,
17 tu.age,
18 tu.weight
19 FROM training_users tu
20 JOIN users u ON u.user_id = tu.user_id
21),
22monthly_sessions AS (
23 SELECT
24 tb.user_id,
25 m.month_no,
26 COALESCE(COUNT(ts.training_id), 0) AS sessions_count,
27 COALESCE(SUM(ts.duration), 0) AS total_duration_minutes,
28 COALESCE(SUM(ts.calories), 0) AS total_calories,
29 COALESCE(AVG(ts.duration), 0) AS avg_session_duration,
30 COALESCE(AVG(ts.calories), 0) AS avg_session_calories
31 FROM training_base tb
32 CROSS JOIN months m
33 LEFT JOIN training_sessions ts
34 ON ts.training_user_id = tb.user_id
35 AND EXTRACT(YEAR FROM ts.date)::int = (SELECT report_year FROM params)
36 AND EXTRACT(MONTH FROM ts.date)::int = m.month_no
37 GROUP BY tb.user_id, m.month_no
38),
39monthly_ranked AS (
40 SELECT
41 ms.*,
42 DENSE_RANK() OVER (PARTITION BY ms.user_id ORDER BY ms.total_calories DESC, ms.month_no ASC) AS peak_calorie_month_rank,
43 DENSE_RANK() OVER (PARTITION BY ms.user_id ORDER BY ms.sessions_count DESC, ms.month_no ASC) AS peak_sessions_month_rank
44 FROM monthly_sessions ms
45),
46active_month_streaks AS (
47 SELECT
48 user_id,
49 month_no,
50 month_no - ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY month_no) AS grp
51 FROM monthly_sessions
52 WHERE sessions_count > 0
53),
54longest_streak AS (
55 SELECT
56 user_id,
57 MAX(streak_len) AS longest_active_month_streak
58 FROM (
59 SELECT user_id, grp, COUNT(*) AS streak_len
60 FROM active_month_streaks
61 GROUP BY user_id, grp
62 ) s
63 GROUP BY user_id
64),
65annual_training AS (
66 SELECT
67 user_id,
68 SUM(sessions_count) AS annual_sessions,
69 SUM(total_duration_minutes) AS annual_duration_minutes,
70 SUM(total_calories) AS annual_calories,
71 AVG(total_duration_minutes) AS avg_monthly_duration,
72 AVG(total_calories) AS avg_monthly_calories,
73 COUNT(*) FILTER (WHERE sessions_count > 0) AS active_months,
74 REGR_SLOPE(total_calories::numeric, month_no::numeric) AS calories_trend_slope,
75 REGR_SLOPE(total_duration_minutes::numeric, month_no::numeric) AS duration_trend_slope
76 FROM monthly_sessions
77 GROUP BY user_id
78),
79peak_months AS (
80 SELECT
81 user_id,
82 MAX(month_no) FILTER (WHERE peak_calorie_month_rank = 1) AS peak_calorie_month_no,
83 MAX(month_no) FILTER (WHERE peak_sessions_month_rank = 1) AS peak_sessions_month_no
84 FROM monthly_ranked
85 GROUP BY user_id
86)
87SELECT
88 tb.user_id,
89 tb.username,
90 tb.email,
91 tb.gender,
92 tb.age,
93 tb.weight,
94 at.annual_sessions,
95 ROUND(at.annual_duration_minutes::numeric, 2) AS annual_duration_minutes,
96 ROUND(at.annual_calories::numeric, 2) AS annual_calories,
97 at.active_months,
98 ROUND((at.active_months / 12.0)::numeric, 4) AS consistency_ratio,
99 COALESCE(ls.longest_active_month_streak, 0) AS longest_active_month_streak,
100 pm.peak_calorie_month_no,
101 pm.peak_sessions_month_no,
102 ROUND(COALESCE(at.calories_trend_slope, 0)::numeric, 4) AS calories_trend_slope,
103 ROUND(COALESCE(at.duration_trend_slope, 0)::numeric, 4) AS duration_trend_slope,
104 DENSE_RANK() OVER (
105 ORDER BY
106 at.annual_calories DESC,
107 at.active_months DESC,
108 COALESCE(ls.longest_active_month_streak, 0) DESC,
109 tb.user_id ASC
110 ) AS training_annual_rank
111FROM training_base tb
112JOIN annual_training at ON at.user_id = tb.user_id
113JOIN peak_months pm ON pm.user_id = tb.user_id
114LEFT JOIN longest_streak ls ON ls.user_id = tb.user_id
115ORDER BY training_annual_rank, tb.user_id;
116
Note: See TracBrowser for help on using the repository browser.