source: db-scripts/p6_q3_annual_discipline_adherence_streaks.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: 4.4 KB
Line 
1SET search_path TO trekr;
2
3-- P6 Q3 (Annual): Discipline adherence, completion quality, and streak behavior.
4-- Change report_year in params CTE when needed.
5WITH params AS (
6 SELECT 2026::int AS report_year
7),
8discipline_base AS (
9 SELECT
10 du.user_id,
11 u.username,
12 u.email
13 FROM discipline_users du
14 JOIN users u ON u.user_id = du.user_id
15),
16task_mix AS (
17 SELECT
18 COALESCE(t.discipline_user_id, c.user_id) AS user_id,
19 COUNT(*) AS total_tasks_defined,
20 COUNT(*) FILTER (WHERE t.custom_tracking_id IS NULL) AS core_tasks,
21 COUNT(*) FILTER (WHERE t.custom_tracking_id IS NOT NULL) AS custom_tasks,
22 COUNT(DISTINCT COALESCE(t.custom_tracking_id::text, 'core')) AS task_category_span
23 FROM tasks t
24 LEFT JOIN custom_tracking_categories c
25 ON c.custom_tracking_id = t.custom_tracking_id
26 WHERE t.discipline_user_id IS NOT NULL
27 OR t.custom_tracking_id IS NOT NULL
28 GROUP BY COALESCE(t.discipline_user_id, c.user_id)
29),
30annual_daily_completion AS (
31 SELECT
32 dc.user_id,
33 dc.date,
34 COALESCE(dc.procent, 0) AS procent,
35 CASE WHEN COALESCE(dc.procent, 0) >= 80 THEN 1 ELSE 0 END AS strong_day
36 FROM daily_completion dc
37 WHERE EXTRACT(YEAR FROM dc.date)::int = (SELECT report_year FROM params)
38),
39daily_completion_stats AS (
40 SELECT
41 adc.user_id,
42 COUNT(*) AS tracked_days,
43 AVG(adc.procent) AS avg_completion_percent,
44 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY adc.procent) AS median_completion_percent,
45 COUNT(*) FILTER (WHERE adc.procent = 100) AS perfect_days,
46 COUNT(*) FILTER (WHERE adc.procent >= 80) AS strong_days,
47 STDDEV_SAMP(adc.procent) AS completion_variability
48 FROM annual_daily_completion adc
49 GROUP BY adc.user_id
50),
51strong_day_streaks AS (
52 SELECT
53 user_id,
54 date,
55 date - (ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date))::int AS grp
56 FROM annual_daily_completion
57 WHERE strong_day = 1
58),
59longest_strong_streak AS (
60 SELECT
61 user_id,
62 MAX(streak_len) AS longest_strong_day_streak
63 FROM (
64 SELECT user_id, grp, COUNT(*) AS streak_len
65 FROM strong_day_streaks
66 GROUP BY user_id, grp
67 ) s
68 GROUP BY user_id
69),
70annual_task_execution AS (
71 SELECT
72 dc.user_id,
73 COUNT(tdc.task_id) AS completed_task_events
74 FROM daily_completion dc
75 LEFT JOIN task_daily_completion tdc
76 ON tdc.daily_completion_id = dc.daily_completion_id
77 WHERE EXTRACT(YEAR FROM dc.date)::int = (SELECT report_year FROM params)
78 GROUP BY dc.user_id
79)
80SELECT
81 db.user_id,
82 db.username,
83 db.email,
84 COALESCE(tm.total_tasks_defined, 0) AS total_tasks_defined,
85 COALESCE(tm.core_tasks, 0) AS core_tasks,
86 COALESCE(tm.custom_tasks, 0) AS custom_tasks,
87 COALESCE(tm.task_category_span, 0) AS task_category_span,
88 COALESCE(dcs.tracked_days, 0) AS tracked_days,
89 ROUND(COALESCE(dcs.avg_completion_percent, 0)::numeric, 2) AS avg_completion_percent,
90 ROUND(COALESCE(dcs.median_completion_percent, 0)::numeric, 2) AS median_completion_percent,
91 COALESCE(dcs.perfect_days, 0) AS perfect_days,
92 COALESCE(dcs.strong_days, 0) AS strong_days,
93 ROUND(COALESCE(dcs.completion_variability, 0)::numeric, 4) AS completion_variability,
94 COALESCE(ate.completed_task_events, 0) AS completed_task_events,
95 COALESCE(lss.longest_strong_day_streak, 0) AS longest_strong_day_streak,
96 ROUND(
97 COALESCE((COALESCE(dcs.strong_days, 0) / NULLIF(COALESCE(dcs.tracked_days, 0), 0)::numeric), 0),
98 4
99 ) AS strong_day_ratio,
100 ROUND(
101 (
102 COALESCE(dcs.avg_completion_percent, 0) * 0.45
103 + COALESCE(lss.longest_strong_day_streak, 0) * 2.00
104 + COALESCE(ate.completed_task_events, 0) * 0.35
105 )::numeric,
106 2
107 ) AS discipline_composite_score,
108 DENSE_RANK() OVER (
109 ORDER BY
110 (
111 COALESCE(dcs.avg_completion_percent, 0) * 0.45
112 + COALESCE(lss.longest_strong_day_streak, 0) * 2.00
113 + COALESCE(ate.completed_task_events, 0) * 0.35
114 ) DESC,
115 db.user_id ASC
116 ) AS discipline_annual_rank
117FROM discipline_base db
118LEFT JOIN task_mix tm ON tm.user_id = db.user_id
119LEFT JOIN daily_completion_stats dcs ON dcs.user_id = db.user_id
120LEFT JOIN annual_task_execution ate ON ate.user_id = db.user_id
121LEFT JOIN longest_strong_streak lss ON lss.user_id = db.user_id
122ORDER BY discipline_annual_rank, db.user_id;
123
124
Note: See TracBrowser for help on using the repository browser.