Business Context
You work on the analytics team for a wearable-health platform (think WHOOP/Oura-like) with 3M monthly active users. The product team is building an in-app “Readiness & Wellness Trends” dashboard that helps users understand whether their recovery is improving or declining. The dashboard needs a compact dataset that a BI tool (Looker/Tableau) can visualize as: (a) a daily readiness line chart, (b) a 7-day moving average line, and (c) a “trend” indicator (up/down/flat) comparing recent vs prior periods.
The data model is typical of consumer health: one row per user per day with readiness and a few wellness indicators. Users can have missing days (device not worn), and the dashboard should only consider days with a valid readiness score.
Task
Write a SQL query that produces a daily time series for each user over their most recent 14 days of data, including a 7-day moving average and a trend label that can be directly used for visualization.
Requirements
- Consider only rows where
readiness_score is not NULL.
- For each
user_id, find the latest metric_date available and return the 14 most recent days up to that date (not “last 14 calendar days”).
- Output one row per
user_id and metric_date with:
readiness_score
sleep_hours
resting_hr
readiness_7d_ma: 7-row moving average of readiness (current day + previous 6 available days)
- Add
trend_label computed per user as:
UP if avg readiness over the most recent 7 rows is >= prior 7 rows + 5 points
DOWN if it is <= prior 7 rows - 5 points
- otherwise
FLAT
- Order results by
user_id, then metric_date ascending.
Table Definitions
users
| column | type | description |
|---|
| user_id | INT | Primary key for the user |
| signup_date | DATE | Date the user created an account |
| country | VARCHAR(2) | ISO country code |
daily_wellness_metrics
| column | type | description |
|---|
| user_id | INT | FK to users.user_id |
| metric_date | DATE | Local date of the measurement |
| readiness_score | INT | 0–100 readiness score; NULL if no wearable data |
| sleep_hours | DECIMAL(4,2) | Total sleep duration in hours |
| resting_hr | INT | Resting heart rate (bpm) |
Sample Data
users
| user_id | signup_date | country |
|---|
| 101 | 2024-12-15 | US |
| 202 | 2025-01-05 | GB |
| 303 | 2025-01-20 | US |
daily_wellness_metrics
| user_id | metric_date | readiness_score | sleep_hours | resting_hr |
|---|
| 101 | 2025-02-01 | 62 | 6.80 | 58 |
| 101 | 2025-02-02 | 65 | 7.10 | 57 |
| 101 | 2025-02-03 | 70 | 7.50 | 56 |
| 101 | 2025-02-04 | 72 | 7.40 | 55 |
| 101 | 2025-02-05 | 74 | 7.80 | 55 |
| 202 | 2025-02-02 | 48 | 5.90 | 64 |
| 202 | 2025-02-03 | 50 | 6.10 | 63 |
| 202 | 2025-02-04 | 52 | 6.20 | 62 |
| 202 | 2025-02-05 | 55 | 6.50 | 61 |
| 303 | 2025-02-05 | 80 | 8.10 | 52 |
Expected Output (with sample data)
(Only a subset shown; your query should generalize.)
| user_id | metric_date | readiness_score | sleep_hours | resting_hr | readiness_7d_ma | trend_label |
|---|
| 101 | 2025-02-01 | 62 | 6.80 | 58 | 62.00 | FLAT |
| 101 | 2025-02-02 | 65 | 7.10 | 57 | 63.50 | FLAT |
| 101 | 2025-02-03 | 70 | 7.50 | 56 | 65.67 | FLAT |
| 101 | 2025-02-04 | 72 | 7.40 | 55 | 67.25 | FLAT |
| 101 | 2025-02-05 | 74 | 7.80 | 55 | 68.60 | FLAT |
| 202 | 2025-02-02 | 48 | 5.90 | 64 | 48.00 | FLAT |
| 202 | 2025-02-03 | 50 | 6.10 | 63 | 49.00 | FLAT |
| 202 | 2025-02-04 | 52 | 6.20 | 62 | 50.00 | FLAT |
| 202 | 2025-02-05 | 55 | 6.50 | 61 | 51.25 | FLAT |
| 303 | 2025-02-05 | 80 | 8.10 | 52 | 80.00 | FLAT |