| | 298 | WITH course_year_performance AS ( |
| | 299 | SELECT |
| | 300 | EXTRACT(YEAR FROM qa.attempt_date) AS year, |
| | 301 | c.course_id, |
| | 302 | ROUND(AVG(qa.score), 2) AS final_grade_per_course |
| | 303 | FROM quiz_attempt qa |
| | 304 | JOIN quiz q |
| | 305 | ON q.quiz_id = qa.quiz_id |
| | 306 | JOIN lesson l |
| | 307 | ON l.lesson_id = q.lesson_id |
| | 308 | JOIN module m |
| | 309 | ON m.module_id = l.module_id |
| | 310 | JOIN course c |
| | 311 | ON c.course_id = m.course_id |
| | 312 | GROUP BY |
| | 313 | EXTRACT(YEAR FROM qa.attempt_date), |
| | 314 | c.course_id |
| | 315 | ), |
| | 316 | year_course_summary AS ( |
| | 317 | SELECT |
| | 318 | year, |
| | 319 | ROUND(AVG(final_grade_per_course), 2) AS final_year_success |
| | 320 | FROM course_year_performance |
| | 321 | GROUP BY year |
| | 322 | ) |
| 299 | | EXTRACT(YEAR FROM qa.attempt_date) AS Year, |
| 300 | | cat.name AS Category_Name, |
| 301 | | COUNT(DISTINCT qa.attempt_id) AS Total_Attempts, |
| 302 | | COUNT(DISTINCT qa.user_id) AS Total_Students, |
| 303 | | ROUND(AVG(qa.score), 2) AS Avg_Score, |
| 304 | | COUNT( |
| 305 | | DISTINCT CASE |
| 306 | | WHEN qa.score >= q.passing_score |
| 307 | | THEN qa.attempt_id |
| 308 | | END |
| 309 | | ) AS Passed_Attempts, |
| 310 | | ROUND( |
| 311 | | COUNT( |
| 312 | | DISTINCT CASE |
| 313 | | WHEN qa.score >= q.passing_score |
| 314 | | THEN qa.attempt_id |
| 315 | | END |
| 316 | | )::DECIMAL / |
| 317 | | NULLIF(COUNT(DISTINCT qa.attempt_id),0) * 100, |
| 318 | | 2 |
| 319 | | ) AS Pass_Rate_Percentage |
| 320 | | FROM quiz_attempt qa |
| 321 | | JOIN quiz q |
| 322 | | ON q.quiz_id = qa.quiz_id |
| 323 | | JOIN lesson l |
| 324 | | ON l.lesson_id = q.lesson_id |
| 325 | | JOIN module m |
| 326 | | ON m.module_id = l.module_id |
| | 324 | EXTRACT(YEAR FROM e.enroll_date) AS year, |
| | 325 | COUNT(DISTINCT c.instructor_id) AS total_instructor_activity, |
| | 326 | COUNT(DISTINCT e.user_id) AS total_students, |
| | 327 | COUNT(DISTINCT e.enrollment_id) AS total_enrollments, |
| | 328 | COUNT(DISTINCT qa.attempt_id) AS total_attempts, |
| | 329 | COUNT(DISTINCT CASE |
| | 330 | WHEN e.completion_status = 'COMPLETED' THEN e.enrollment_id |
| | 331 | END) AS completed_enrollments, |
| | 332 | COUNT(DISTINCT cert.certificate_id) AS total_certificates, |
| | 333 | ROUND(AVG(e.progress_percentage), 2) AS avg_student_success_within_courses, |
| | 334 | ROUND(AVG(qa.score), 2) AS avg_final_grade_per_course, ycs.final_year_success |
| | 335 | FROM enrollment e |
| 328 | | ON c.course_id = m.course_id |
| 329 | | JOIN course_category cc |
| 330 | | ON cc.course_id = c.course_id |
| 331 | | JOIN category cat |
| 332 | | ON cat.category_id = cc.category_id |
| | 337 | ON c.course_id = e.course_id |
| | 338 | LEFT JOIN certificate cert |
| | 339 | ON cert.enrollment_id = e.enrollment_id |
| | 340 | LEFT JOIN module m |
| | 341 | ON m.course_id = c.course_id |
| | 342 | LEFT JOIN lesson l |
| | 343 | ON l.module_id = m.module_id |
| | 344 | LEFT JOIN quiz q |
| | 345 | ON q.lesson_id = l.lesson_id |
| | 346 | LEFT JOIN quiz_attempt qa |
| | 347 | ON qa.quiz_id = q.quiz_id |
| | 348 | AND qa.user_id = e.user_id |
| | 349 | LEFT JOIN year_course_summary ycs |
| | 350 | ON ycs.year = EXTRACT(YEAR FROM e.enroll_date) |
| | 360 | - E(enrollment_id, user_id, course_id, enroll_date, completion_status, progress_percentage) |
| | 361 | - C(course_id, name, price, status, instructor_id) |
| | 362 | - CERT(certificate_id, enrollment_id, issue_date, certificate_code, status) |
| | 363 | - M(module_id, course_id, title, description) |
| | 364 | - L(lesson_id, module_id, title, material) |
| | 365 | - Q(quiz_id, total_points, passing_score, lesson_id) |
| 346 | | - Q(quiz_id, total_points, passing_score, lesson_id) |
| 347 | | - L(lesson_id, module_id, title, material) |
| 348 | | - M(module_id, course_id, title, description) |
| 349 | | - C(course_id, name, price, status, instructor_id) |
| 350 | | - CC(course_id, category_id) |
| 351 | | - CAT(category_id, name, description) |
| 356 | | J1 ← QA ⋈ QA.quiz_id = Q.quiz_id Q |
| 357 | | |
| 358 | | J2 ← J1 ⋈ Q.lesson_id = L.lesson_id L |
| 359 | | |
| 360 | | J3 ← J2 ⋈ L.module_id = M.module_id M |
| 361 | | |
| 362 | | J4 ← J3 ⋈ M.course_id = C.course_id C |
| 363 | | |
| 364 | | J5 ← J4 ⋈ C.course_id = CC.course_id CC |
| 365 | | |
| 366 | | J6 ← J5 ⋈ CC.category_id = CAT.category_id CAT |
| 367 | | |
| 368 | | **Projection and renaming** |
| 369 | | |
| 370 | | F1 ← π attempt_id, user_id, score, passing_score, CAT.name → Category_Name, YEAR(attempt_date) → Year (J6) |
| 371 | | |
| | 371 | J1 ← E ⋈ E.course_id = C.course_id C |
| | 372 | |
| | 373 | J2 ← J1 ⟕ E.enrollment_id = CERT.enrollment_id CERT |
| | 374 | |
| | 375 | J3 ← J2 ⟕ C.course_id = M.course_id M |
| | 376 | |
| | 377 | J4 ← J3 ⟕ M.module_id = L.module_id L |
| | 378 | |
| | 379 | J5 ← J4 ⟕ L.lesson_id = Q.lesson_id Q |
| | 380 | |
| | 381 | J6 ← J5 ⟕ (Q.quiz_id = QA.quiz_id ∧ QA.user_id = E.user_id) QA |
| | 382 | |
| | 383 | **Projection with date transformation** |
| | 384 | |
| | 385 | F1 ← π enrollment_id, user_id, instructor_id, completion_status, progress_percentage, certificate_id, attempt_id, score, course_id, |
| | 386 | YEAR(enroll_date) → Year (J6) |
| 379 | | COUNT(DISTINCT user_id) → Total_Students, |
| 380 | | |
| 381 | | AVG(score) → Avg_Score, |
| 382 | | |
| 383 | | COUNT(DISTINCT [score ≥ passing_score] attempt_id) → Passed_Attempts (F1) |
| 384 | | |
| 385 | | **Final projection and percentage calculation** |
| 386 | | |
| 387 | | P ← π Year, Category_Name, Total_Attempts, Total_Students, Avg_Score, Passed_Attempts, |
| 388 | | |
| 389 | | (Passed_Attempts / Total_Attempts) * 100 → Pass_Rate_Percentage (G) |
| | 400 | COUNT(DISTINCT [completion_status = 'COMPLETED'] enrollment_id) → Completed_Enrollments, |
| | 401 | |
| | 402 | COUNT(DISTINCT certificate_id) → Total_Certificates, |
| | 403 | |
| | 404 | AVG(progress_percentage) → Avg_Student_Success_Within_Courses, |
| | 405 | |
| | 406 | AVG(score) → Avg_Final_Grade_Per_Course (F1) |
| | 407 | |
| | 408 | **Course-level yearly performance** |
| | 409 | |
| | 410 | CP1 ← QA ⋈ QA.quiz_id = Q.quiz_id Q |
| | 411 | |
| | 412 | CP2 ← CP1 ⋈ Q.lesson_id = L.lesson_id L |
| | 413 | |
| | 414 | CP3 ← CP2 ⋈ L.module_id = M.module_id M |
| | 415 | |
| | 416 | CP4 ← CP3 ⋈ M.course_id = C.course_id C |
| | 417 | |
| | 418 | CF ← π course_id, score, YEAR(attempt_date) → Year (CP4) |
| | 419 | |
| | 420 | CG ← Year, course_id γ AVG(score) → Final_Grade_Per_Course (CF) |
| | 421 | |
| | 422 | **Final yearly course success** |
| | 423 | Y ← Year γ AVG(Final_Grade_Per_Course) → Final_Year_Success (CG) |
| | 424 | |
| | 425 | |
| | 426 | **Final join and projection** |
| | 427 | |
| | 428 | R1 ← G ⋈ G.Year = Y.Year Y |
| | 429 | |
| | 430 | P ← π Year, Total_Instructor_Activity, Total_Students, Total_Enrollments, Total_Attempts, Completed_Enrollments, Total_Certificates, Avg_Student_Success_Within_Courses, Avg_Final_Grade_Per_Course, Final_Year_Success (R1) |