Changes between Version 1 and Version 2 of DatabaseProgramming


Ignore:
Timestamp:
06/15/26 20:26:17 (4 days ago)
Author:
231067
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v1 v2  
    169169== Фунцкии
    170170
     171Функцијата `fn_eligibility_matrix` е дизајнирана да ја пресмета матрицата на компатибилност помеѓу одреден студент и ментор, враќајќи ги резултатите во структуриран JSONB формат. По почетната проверка за постоење на корисниците во системот, таа го анализира бројот на заеднички предмети кои ги слушаат или предаваат, како и бројот на заеднички интереси кои ги делат, преку кои се одредува компатибилност. Исто така, функцијата утврдува дали двајцата корисници припаѓаат на ист факултет. Финалната одлука за подобност се носи врз основа на тоа дали корисниците имаат барем еден заеднички предмет или најмалку два заеднички интереси. Сите овие пресметани метрики се подредени во прегледен објект за понатамошна обработка во апликацискиот слој.
     172
     173{{{
     174CREATE OR REPLACE FUNCTION fn_eligibility_matrix(p_student_id BIGINT, p_mentor_id BIGINT)
     175RETURNS JSONB
     176LANGUAGE plpgsql
     177AS $$
     178DECLARE
     179    v_shared_subjects INT;
     180    v_shared_interests INT;
     181    v_same_faculty BOOLEAN;
     182    v_student_fac BIGINT;
     183    v_mentor_fac BIGINT;
     184    v_is_eligible BOOLEAN;
     185BEGIN
     186    -- Проверки дали постојат
     187    IF NOT EXISTS (SELECT 1 FROM "User" WHERE ID = p_student_id) OR NOT EXISTS (SELECT 1 FROM "User" WHERE ID = p_mentor_id) THEN
     188        RETURN jsonb_build_object('error', 'Корисниците не постојат');
     189    END IF;
     190
     191    -- Заеднички предмети
     192    SELECT COUNT(*) INTO v_shared_subjects FROM User_Subject us1
     193    JOIN User_Subject us2 ON us1.SubjectID = us2.SubjectID
     194    WHERE us1.UserID = p_student_id AND us2.UserID = p_mentor_id;
     195
     196    -- Заеднички интереси
     197    SELECT COUNT(*) INTO v_shared_interests FROM User_Interest ui1
     198    JOIN User_Interest ui2 ON ui1.InterestID = ui2.InterestID
     199    WHERE ui1.UserID = p_student_id AND ui2.UserID = p_mentor_id;
     200
     201    -- Факултет
     202    SELECT FacultyID INTO v_student_fac FROM "User" WHERE ID = p_student_id;
     203    SELECT FacultyID INTO v_mentor_fac FROM "User" WHERE ID = p_mentor_id;
     204    v_same_faculty := (v_student_fac = v_mentor_fac);
     205
     206    -- Логика за подобност
     207    v_is_eligible := (v_shared_subjects > 0 OR v_shared_interests >= 2);
     208
     209    RETURN jsonb_build_object(
     210        'student_id', p_student_id,
     211        'mentor_id', p_mentor_id,
     212        'is_eligible', v_is_eligible,
     213        'metrics', jsonb_build_object(
     214            'shared_subjects', v_shared_subjects,
     215            'shared_interests', v_shared_interests,
     216            'same_faculty', v_same_faculty
     217        )
     218    );
     219END;
     220$$;
     221
     222SELECT fn_eligibility_matrix(1, 2);
     223}}}
     224
     225----
     226
     227Функцијата `fn_mentor_bottleneck_score` служи за пресметување на нумерички индекс кој го рефлектира просечното доцнење на одреден ментор при реализација на задачите со неговите студенти. Таа ги анализира сите активни задачи за кои е задолжен менторот, а чиј краен рок е веќе поминат, па го собира вкупниот број на денови на доцнење во однос на тековниот датум. Доколку менторот нема активни задачи кои доцнат, функцијата веднаш враќа вредност нула. Во спротивно, таа го пресметува просечниот број на денови на доцнење по задача и го заокружува овој резултат на две децимали, овозможувајќи лесна детекција на ментори кои претставуваат тесно грло во процесот.
     228
     229{{{
     230CREATE OR REPLACE FUNCTION fn_mentor_bottleneck_score(p_mentor_id BIGINT)
     231RETURNS NUMERIC
     232LANGUAGE plpgsql
     233AS $$
     234DECLARE
     235    v_total_overdue_days NUMERIC;
     236    v_active_tasks INT;
     237BEGIN
     238    SELECT
     239        COALESCE(SUM(EXTRACT(DAY FROM (CURRENT_DATE - t.EndDate))), 0),
     240        COUNT(t.ID)
     241    INTO v_total_overdue_days, v_active_tasks
     242    FROM Task t
     243    JOIN Mentorship m ON t.MentorshipID = m.ID
     244    WHERE m.MentorID = p_mentor_id AND t.Status = 0 AND t.EndDate < CURRENT_DATE;
     245
     246    IF v_active_tasks = 0 THEN
     247        RETURN 0.00;
     248    END IF;
     249
     250    -- Формула: Просечно доцнење во денови по задача
     251    RETURN ROUND(v_total_overdue_days / v_active_tasks, 2);
     252END;
     253$$;
     254
     255SELECT fn_mentor_bottleneck_score(2);
     256}}}
     257
     258----
     259
     260Функцијата `fn_predict_completion_date` користи едноставен алгоритам за предвидување на точниот датум и време кога би завршило одредено менторство врз основа на досегашната динамика на работа. Таа го извлекува бројот на завршени и преостанати задачи за менторството, како и датумот кога е започната првата задача. Доколку нема доволно историски податоци, односно ако нема ниту една завршена или преостаната задача, функцијата враќа празна (NULL) вредност. Ако податоците се достапни, таа го пресметува просечното време потребно за извршување на една задача и го множи со бројот на преостанати задачи, додавајќи го овој временски интервал на тековното време за да пресмета крајна временска прогноза.
     261
     262{{{
     263CREATE OR REPLACE FUNCTION fn_predict_completion_date(p_mentorship_id BIGINT)
     264RETURNS TIMESTAMP
     265LANGUAGE plpgsql
     266AS $$
     267DECLARE
     268    v_completed INT;
     269    v_pending INT;
     270    v_avg_days_per_task NUMERIC;
     271    v_start_date TIMESTAMP;
     272BEGIN
     273    SELECT COUNT(*) FILTER (WHERE Status = 1), COUNT(*) FILTER (WHERE Status = 0), MIN(StartDate)
     274    INTO v_completed, v_pending, v_start_date
     275    FROM Task WHERE MentorshipID = p_mentorship_id;
     276
     277    -- Нема доволно податоци
     278    IF v_completed = 0 OR v_pending = 0 THEN
     279        RETURN NULL;
     280    END IF;
     281
     282    -- Колку денови му требале во просек за една задача
     283    v_avg_days_per_task := EXTRACT(DAY FROM (CURRENT_TIMESTAMP - v_start_date)) / v_completed;
     284   
     285    -- Прогноза: Денес + (Просек * Останати Задачи)
     286    RETURN CURRENT_TIMESTAMP + (v_avg_days_per_task * v_pending || ' days')::INTERVAL;
     287END;
     288$$;
     289
     290SELECT fn_predict_completion_date(9887604);
     291}}}
     292
    171293== Тригери