-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPespi Database Assignment Questions.sql
More file actions
401 lines (361 loc) · 11.5 KB
/
Copy pathPespi Database Assignment Questions.sql
File metadata and controls
401 lines (361 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
-- Pespi Database Assignment Questions
-- This file contains SQL queries, procedures, and views that exist in the web application
-- but are not explicitly defined in the database schema file
-- =============================================
-- 1. COMPLEX QUERIES WITH JOINS
-- =============================================
-- Query 1: Get user's workout history with workout template details
-- This query joins UserWorkouts with WorkoutTemplates to get complete workout information
SELECT
uw.user_workout_id,
uw.user_id,
uw.log_date,
uw.sets,
uw.reps,
uw.duration_min,
uw.calories_burned,
uw.workout_date,
uw.notes,
wt.exercise_name,
wt.exercise_type,
wt.muscle_group,
wt.difficulty_level
FROM "UserWorkouts" uw
JOIN "WorkoutTemplates" wt ON uw.workout_id = wt.workout_id
WHERE uw.user_id = :user_id
ORDER BY uw.workout_date DESC;
-- Query 2: Get nutrition summary for a date range
-- This query aggregates meal tracking data to provide nutrition summaries
SELECT
mt.user_id,
mt.log_date,
SUM(mt.calories) AS total_calories,
SUM(mt.protein) AS total_protein,
SUM(mt.carbs) AS total_carbs,
SUM(mt.fats) AS total_fats,
COUNT(mt.meal_id) AS meal_count
FROM "MealTrackings" mt
WHERE mt.user_id = :user_id
AND mt.log_date BETWEEN :start_date AND :end_date
GROUP BY mt.user_id, mt.log_date
ORDER BY mt.log_date DESC;
-- Query 3: Get workout statistics by muscle group
-- This query joins UserWorkouts with WorkoutTemplates and aggregates by muscle group
SELECT
wt.muscle_group,
COUNT(uw.user_workout_id) AS workout_count,
SUM(uw.calories_burned) AS total_calories_burned,
AVG(uw.duration_min) AS avg_duration
FROM "UserWorkouts" uw
JOIN "WorkoutTemplates" wt ON uw.workout_id = wt.workout_id
WHERE uw.user_id = :user_id
GROUP BY wt.muscle_group
ORDER BY workout_count DESC;
-- =============================================
-- 2. QUERIES WITH AGGREGATIONS
-- =============================================
-- Query 4: Get average daily calories for the last 7 days
SELECT
log_date,
SUM(calories) AS total_calories
FROM "MealTrackings"
WHERE user_id = :user_id
AND log_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY log_date
ORDER BY log_date DESC;
-- Query 5: Get average macronutrient distribution
SELECT
AVG(protein) AS avg_protein,
AVG(carbs) AS avg_carbs,
AVG(fats) AS avg_fats
FROM "MealTrackings"
WHERE user_id = :user_id
AND log_date >= CURRENT_DATE - INTERVAL '7 days';
-- =============================================
-- 3. QUERIES USING VIEWS
-- =============================================
-- Query 6: Using the user_workout_summary view
SELECT * FROM user_workout_summary
WHERE user_id = :user_id;
-- Query 7: Using the nutrition_summary view
SELECT * FROM nutrition_summary
WHERE user_id = :user_id
AND date >= CURRENT_DATE - INTERVAL '7 days'
ORDER BY date DESC;
-- =============================================
-- 4. QUERIES WITH SUBQUERIES
-- =============================================
-- Query 8: Find users who have completed more workouts than the average
SELECT
u.user_id,
u.name,
COUNT(uw.user_workout_id) AS workout_count
FROM "Users" u
JOIN "UserWorkouts" uw ON u.user_id = uw.user_id
GROUP BY u.user_id, u.name
HAVING COUNT(uw.user_workout_id) > (
SELECT AVG(workout_count)
FROM (
SELECT COUNT(*) AS workout_count
FROM "UserWorkouts"
GROUP BY user_id
) AS workout_counts
)
ORDER BY workout_count DESC;
-- Query 9: Find workouts with calories burned higher than the user's average
SELECT
uw.user_workout_id,
uw.workout_date,
uw.calories_burned,
wt.exercise_name
FROM "UserWorkouts" uw
JOIN "WorkoutTemplates" wt ON uw.workout_id = wt.workout_id
WHERE uw.user_id = :user_id
AND uw.calories_burned > (
SELECT AVG(calories_burned)
FROM "UserWorkouts"
WHERE user_id = :user_id
)
ORDER BY uw.calories_burned DESC;
-- =============================================
-- 5. STORED PROCEDURES
-- =============================================
-- Procedure 1: Calculate user's BMI and update weight tracking
CREATE OR REPLACE PROCEDURE update_user_bmi(
p_user_id INTEGER,
p_weight NUMERIC,
p_height NUMERIC
)
LANGUAGE plpgsql
AS $$
DECLARE
v_bmi NUMERIC;
BEGIN
-- Calculate BMI: weight (kg) / height (m)²
v_bmi := p_weight / (p_height * p_height);
-- Insert new weight tracking record with calculated BMI
INSERT INTO "WeightTrackings" (
user_id,
recorded_at,
weight,
bmi,
"createdAt",
"updatedAt"
)
VALUES (
p_user_id,
CURRENT_TIMESTAMP,
p_weight,
v_bmi,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
);
-- Update user's height if needed
UPDATE "Users"
SET user_height = p_height
WHERE user_id = p_user_id;
END;
$$;
-- Procedure 2: Generate weekly fitness report
CREATE OR REPLACE PROCEDURE generate_weekly_report(
p_user_id INTEGER,
p_start_date DATE
)
LANGUAGE plpgsql
AS $$
DECLARE
v_end_date DATE;
v_total_workouts INTEGER;
v_total_calories_burned NUMERIC;
v_avg_daily_calories NUMERIC;
v_weight_change NUMERIC;
v_start_weight NUMERIC;
v_end_weight NUMERIC;
BEGIN
-- Calculate end date (7 days after start date)
v_end_date := p_start_date + INTERVAL '7 days';
-- Get workout statistics
SELECT
COUNT(*),
COALESCE(SUM(calories_burned), 0)
INTO
v_total_workouts,
v_total_calories_burned
FROM "UserWorkouts"
WHERE user_id = p_user_id
AND workout_date >= p_start_date
AND workout_date < v_end_date;
-- Get calorie intake statistics
SELECT COALESCE(AVG(daily_calories), 0)
INTO v_avg_daily_calories
FROM (
SELECT log_date, SUM(calories) AS daily_calories
FROM "MealTrackings"
WHERE user_id = p_user_id
AND log_date >= p_start_date
AND log_date < v_end_date
GROUP BY log_date
) AS daily_totals;
-- Get weight change
SELECT weight INTO v_start_weight
FROM "WeightTrackings"
WHERE user_id = p_user_id
AND recorded_at <= p_start_date
ORDER BY recorded_at DESC
LIMIT 1;
SELECT weight INTO v_end_weight
FROM "WeightTrackings"
WHERE user_id = p_user_id
AND recorded_at <= v_end_date
ORDER BY recorded_at DESC
LIMIT 1;
v_weight_change := COALESCE(v_end_weight, 0) - COALESCE(v_start_weight, 0);
-- Output the report (in a real application, this would be returned or stored)
RAISE NOTICE 'Weekly Fitness Report for User %', p_user_id;
RAISE NOTICE 'Period: % to %', p_start_date, v_end_date - INTERVAL '1 day';
RAISE NOTICE 'Total Workouts: %', v_total_workouts;
RAISE NOTICE 'Total Calories Burned: %', v_total_calories_burned;
RAISE NOTICE 'Average Daily Calorie Intake: %', v_avg_daily_calories;
RAISE NOTICE 'Weight Change: % lbs', v_weight_change;
END;
$$;
-- =============================================
-- 6. VIEWS
-- =============================================
-- View 1: User Workout Summary
CREATE OR REPLACE VIEW user_workout_summary AS
SELECT
u.user_id,
u.name AS username,
COUNT(uw.user_workout_id) AS total_workouts,
AVG(uw.duration_min) AS avg_duration,
SUM(uw.calories_burned) AS total_calories_burned,
MAX(uw.workout_date) AS last_workout_date
FROM "Users" u
LEFT JOIN "UserWorkouts" uw ON u.user_id = uw.user_id
GROUP BY u.user_id, u.name;
-- View 2: Exercise Progress
CREATE OR REPLACE VIEW exercise_progress AS
SELECT
uw.user_workout_id AS exercise_id,
wt.exercise_name,
u.name AS username,
uw.workout_date AS date,
uw.sets,
uw.reps,
uw.calories_burned AS weight,
LAG(uw.calories_burned) OVER (PARTITION BY wt.exercise_name ORDER BY uw.workout_date) AS previous_weight
FROM "UserWorkouts" uw
JOIN "WorkoutTemplates" wt ON uw.workout_id = wt.workout_id
JOIN "Users" u ON uw.user_id = u.user_id;
-- View 3: Nutrition Summary
CREATE OR REPLACE VIEW nutrition_summary AS
SELECT
mt.user_id,
u.name AS username,
mt.log_date AS date,
SUM(mt.calories) AS daily_calories,
COUNT(mt.meal_id) AS meals_count,
AVG(mt.protein) AS avg_protein,
AVG(mt.carbs) AS avg_carbs,
AVG(mt.fats) AS avg_fat
FROM "MealTrackings" mt
JOIN "Users" u ON mt.user_id = u.user_id
GROUP BY mt.user_id, u.name, mt.log_date;
-- View 4: Weight Progress
CREATE OR REPLACE VIEW weight_progress AS
SELECT
wt.user_id,
u.name AS username,
wt.recorded_at AS date,
wt.weight,
LAG(wt.weight) OVER (PARTITION BY wt.user_id ORDER BY wt.recorded_at) AS previous_weight,
wt.weight - LAG(wt.weight) OVER (PARTITION BY wt.user_id ORDER BY wt.recorded_at) AS weight_change
FROM "WeightTrackings" wt
JOIN "Users" u ON wt.user_id = u.user_id;
-- =============================================
-- 7. TRIGGERS
-- =============================================
-- Trigger 1: Update total calories in meals table when meal items are added/updated/deleted
CREATE OR REPLACE FUNCTION update_meal_calories()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
UPDATE "MealTrackings"
SET calories = (
SELECT COALESCE(SUM(calories), 0)
FROM "MealTrackings"
WHERE user_id = NEW.user_id
AND log_date = NEW.log_date
)
WHERE user_id = NEW.user_id
AND log_date = NEW.log_date;
ELSIF TG_OP = 'DELETE' THEN
UPDATE "MealTrackings"
SET calories = (
SELECT COALESCE(SUM(calories), 0)
FROM "MealTrackings"
WHERE user_id = OLD.user_id
AND log_date = OLD.log_date
)
WHERE user_id = OLD.user_id
AND log_date = OLD.log_date;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_meal_calories_trigger
AFTER INSERT OR UPDATE OR DELETE ON "MealTrackings"
FOR EACH ROW
EXECUTE FUNCTION update_meal_calories();
-- Trigger 2: Prevent negative weights in weight logs
CREATE OR REPLACE FUNCTION prevent_negative_weight()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.weight <= 0 THEN
RAISE EXCEPTION 'Weight cannot be negative or zero';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER prevent_negative_weight_trigger
BEFORE INSERT OR UPDATE ON "WeightTrackings"
FOR EACH ROW
EXECUTE FUNCTION prevent_negative_weight();
-- Trigger 3: Update workout duration based on exercises
CREATE OR REPLACE FUNCTION update_workout_duration()
RETURNS TRIGGER AS $$
BEGIN
UPDATE "UserWorkouts"
SET duration_min = (
SELECT COUNT(*) * 5 -- Assuming 5 minutes per exercise
FROM "UserWorkouts"
WHERE user_id = NEW.user_id
AND workout_date = NEW.workout_date
)
WHERE user_id = NEW.user_id
AND workout_date = NEW.workout_date;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_workout_duration_trigger
AFTER INSERT OR UPDATE OR DELETE ON "UserWorkouts"
FOR EACH ROW
EXECUTE FUNCTION update_workout_duration();
-- Trigger 4: Validate exercise template data
CREATE OR REPLACE FUNCTION validate_exercise_template()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.exercise_name IS NULL OR TRIM(NEW.exercise_name) = '' THEN
RAISE EXCEPTION 'Exercise name cannot be empty';
END IF;
IF NEW.muscle_group IS NULL OR TRIM(NEW.muscle_group) = '' THEN
RAISE EXCEPTION 'Muscle group cannot be empty';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_exercise_template_trigger
BEFORE INSERT OR UPDATE ON "WorkoutTemplates"
FOR EACH ROW
EXECUTE FUNCTION validate_exercise_template();