WITH active_term AS (
SELECT
dct.civ_term_id
, dct.civ_career_term_start_dt
, dct.civ_career_term_end_dt
FROM data_mart.dim_career_term dct
WHERE dct.is_active = 1
LIMIT 1
)
, active_students AS (
SELECT DISTINCT
dp.raw_person_id
, dp.institution_person_id
, dp.dim_person_id
, de.civ_career_id
, dct.civ_term_id
, dp.civ_first_to_attend_college
, dp.is_hispanic
, dp.is_american_indian
, dp.is_asian
, dp.is_white
, dp.is_black
, dp.is_pacific_islander
, dp.raw_gender
, dp.primary_state
FROM data_mart.dim_enrollment de
INNER JOIN data_mart.dim_section ds
ON de.raw_section_id = ds.raw_section_id
INNER JOIN data_mart.dim_career_term dct
ON ds.civ_term_id = dct.civ_term_id
AND de.raw_career_id = dct.raw_career_id
INNER JOIN data_mart.dim_person dp
ON de.raw_person_id = dp.raw_person_id
WHERE
dct.is_active = 1
AND de.raw_career_id <> 'Not Available'
AND de.civ_is_enrolled = 1
)
, latest_persistence_scores AS (
SELECT
acs.dim_person_id
, acs.institution_person_id
, fcs.prediction AS persistence_score
, ROW_NUMBER() OVER (
PARTITION BY acs.dim_person_id
ORDER BY fcs.event_ts DESC
) AS rn
FROM active_students acs
INNER JOIN data_mart.fact_continuation_scores fcs
ON acs.dim_person_id = fcs.dim_person_id
AND acs.civ_career_id = fcs.civ_career
AND acs.civ_term_id = fcs.civ_term_id
)
, low_persistence_students AS (
SELECT
lps.dim_person_id
, lps.institution_person_id
, lps.persistence_score
, 'Low Persistence' AS risk_factor
FROM latest_persistence_scores lps
WHERE lps.rn = 1
AND lps.persistence_score < 0.50
)
, assignment_performance AS (
SELECT
acs.dim_person_id
, acs.institution_person_id
, AVG(CASE
WHEN fagf.raw_student_points_possible > 0
THEN fagf.civ_assignment_grade / fagf.raw_student_points_possible
ELSE fagf.civ_assignment_grade / 100.0
END) AS avg_assignment_grade_pct
, COUNT(fagf.civ_assignment_grade) AS total_assignments
, COUNT(CASE
WHEN (CASE
WHEN fagf.raw_student_points_possible > 0
THEN fagf.civ_assignment_grade / fagf.raw_student_points_possible
ELSE fagf.civ_assignment_grade / 100.0
END) < 0.60
THEN 1
END) AS failing_assignments
FROM active_students acs
INNER JOIN data_mart.fact_assignment_grade_final fagf
ON acs.dim_person_id = fagf.dim_person_id
WHERE fagf.civ_assignment_grade IS NOT NULL
GROUP BY acs.dim_person_id, acs.institution_person_id
)
, poor_assignment_students AS (
SELECT
ap.dim_person_id
, ap.institution_person_id
, ap.avg_assignment_grade_pct
, ap.total_assignments
, ap.failing_assignments
, 'Poor Assignment Performance' AS risk_factor
FROM assignment_performance ap
WHERE
ap.total_assignments >= 2
AND (
ap.avg_assignment_grade_pct < 0.60
OR (ap.failing_assignments::FLOAT / ap.total_assignments) > 0.50
)
)
, term_lms_activity AS (
SELECT
fwa.dim_person_id
, COUNT(fwa.event_ts) AS activity_count
FROM data_mart.fact_web_activity fwa
INNER JOIN active_term at
ON fwa.event_ts BETWEEN at.civ_career_term_start_dt AND CURRENT_DATE
WHERE fwa.civ_activity_type_id IN ('assignment', 'gradebook', 'post')
GROUP BY fwa.dim_person_id
)
, lms_activity_stats AS (
SELECT
AVG(activity_count) AS avg_activity_per_student
, STDDEV(activity_count) AS stddev_activity
FROM term_lms_activity
)
, student_lms_activity AS (
SELECT
acs.dim_person_id
, acs.institution_person_id
, COALESCE(tla.activity_count, 0) AS activity_count
, las.avg_activity_per_student
FROM active_students acs
CROSS JOIN lms_activity_stats las
LEFT JOIN term_lms_activity tla
ON acs.dim_person_id = tla.dim_person_id
)
, reduced_lms_activity_students AS (
SELECT
sla.dim_person_id
, sla.institution_person_id
, sla.activity_count
, sla.avg_activity_per_student
, 'Reduced LMS Activity' AS risk_factor
FROM student_lms_activity sla
WHERE sla.activity_count < (sla.avg_activity_per_student * 0.75)
)
, student_risk_factors AS (
SELECT
acs.dim_person_id
, acs.institution_person_id
, acs.raw_person_id
, acs.civ_career_id
, acs.civ_term_id
, acs.civ_first_to_attend_college
, CASE
WHEN acs.is_hispanic = 1 THEN 'Hispanic/Latino'
WHEN acs.is_black = 1 THEN 'Black/African American'
WHEN acs.is_asian = 1 THEN 'Asian'
WHEN acs.is_white = 1 THEN 'White'
WHEN acs.is_american_indian = 1 THEN 'American Indian/Alaska Native'
WHEN acs.is_pacific_islander = 1 THEN 'Pacific Islander'
ELSE 'Unknown/Other'
END AS race_ethnicity
, acs.raw_gender
, acs.primary_state
, lps.persistence_score
, pas.avg_assignment_grade_pct
, pas.total_assignments
, pas.failing_assignments
, rlas.activity_count AS lms_activity_count
, rlas.avg_activity_per_student AS avg_lms_activity
, CASE WHEN lps.dim_person_id IS NOT NULL THEN 1 ELSE 0 END AS has_low_persistence
, CASE WHEN pas.dim_person_id IS NOT NULL THEN 1 ELSE 0 END AS has_poor_assignments
, CASE WHEN rlas.dim_person_id IS NOT NULL THEN 1 ELSE 0 END AS has_low_lms_activity
FROM active_students acs
LEFT JOIN low_persistence_students lps
ON acs.dim_person_id = lps.dim_person_id
LEFT JOIN poor_assignment_students pas
ON acs.dim_person_id = pas.dim_person_id
LEFT JOIN reduced_lms_activity_students rlas
ON acs.dim_person_id = rlas.dim_person_id
)
, at_risk_students AS (
SELECT
dim_person_id
, institution_person_id
, raw_person_id
, civ_career_id
, civ_term_id
, civ_first_to_attend_college
, race_ethnicity
, raw_gender
, primary_state
, persistence_score
, avg_assignment_grade_pct
, total_assignments
, failing_assignments
, lms_activity_count
, avg_lms_activity
, has_low_persistence
, has_poor_assignments
, has_low_lms_activity
, (has_low_persistence + has_poor_assignments + has_low_lms_activity) AS total_risk_factors
, (has_low_persistence * 3 + has_poor_assignments * 2 + has_low_lms_activity * 1) AS priority_score
FROM student_risk_factors
WHERE (has_low_persistence + has_poor_assignments + has_low_lms_activity) >= 2
)
SELECT
ars.raw_person_id
, ars.institution_person_id
, ars.civ_career_id
, ars.total_risk_factors
, ars.priority_score
, CASE WHEN ars.has_low_persistence = 1
THEN TRIM(TO_CHAR(ars.persistence_score * 100, '990.00')) || '%'
ELSE 'N/A'
END AS persistence_score_percentage
, CASE WHEN ars.has_poor_assignments = 1
THEN TRIM(TO_CHAR(ars.avg_assignment_grade_pct * 100, '990.00')) || '%'
ELSE 'N/A'
END AS avg_assignment_grade_percentage
, CASE WHEN ars.has_low_lms_activity = 1
THEN ars.lms_activity_count::VARCHAR
ELSE 'N/A'
END AS lms_activity_count
, CASE
WHEN ars.civ_first_to_attend_college = 1 THEN 'First Generation'
ELSE 'Non First Generation'
END AS first_gen_status
, COALESCE(ars.race_ethnicity, 'Unknown') AS race_ethnicity
, CASE
WHEN UPPER(ars.raw_gender) IN ('M', 'MALE') THEN 'Male'
WHEN UPPER(ars.raw_gender) IN ('F', 'FEMALE') THEN 'Female'
ELSE 'Other/Unknown'
END AS gender
, COALESCE(ars.primary_state, 'Unknown') AS home_state
, CASE
WHEN ars.total_risk_factors = 3 AND ars.has_low_persistence = 1
THEN 'URGENT: Academic coaching + counseling + LMS training'
WHEN ars.total_risk_factors = 3
THEN 'URGENT: Comprehensive intervention needed'
WHEN ars.has_low_persistence = 1 AND ars.has_poor_assignments = 1
THEN 'HIGH: Tutoring + study skills support'
WHEN ars.has_low_persistence = 1 AND ars.has_low_lms_activity = 1
THEN 'HIGH: Engagement intervention + technical support'
WHEN ars.has_poor_assignments = 1 AND ars.has_low_lms_activity = 1
THEN 'MODERATE: Learning support + engagement strategies'
ELSE 'NORMAL: Monitor closely + targeted support'
END AS intervention_recommendation
FROM at_risk_students ars
ORDER BY
ars.priority_score DESC
, ars.total_risk_factors DESC
, ars.dim_person_id ASC