K87L8BZBS6

DWH-1179 (Metrics)

Dec 24th, 2024
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --- Тестовая таблица для проверки расчета метрик дисциплины ---
  2. CREATE TEMP TABLE dwh_discipline AS
  3. SELECT
  4.     tutor_id,
  5.     ROUND(
  6.         GREATEST(
  7.             1 - SUM(discipline_score) * 1.0 / COUNT(lesson_id),
  8.             0
  9.         ),
  10.         2
  11.     ) AS discipline_all_time,
  12.     ROUND(
  13.         GREATEST(
  14.             1 - SUM(discipline_score) FILTER (WHERE tutor_lesson_number_desc <= 25) * 1.0
  15.                 / COUNT(lesson_id) FILTER (WHERE tutor_lesson_number_desc <= 25),
  16.             0
  17.         ),
  18.         2
  19.     ) AS discipline_25_last_lessons,
  20.     ROUND(
  21.         GREATEST(
  22.             1 - SUM(discipline_score) FILTER (
  23.                 WHERE lesson_started_at BETWEEN tutor_approved_date AND COALESCE(adaptation_complete_date, CURRENT_DATE)
  24.             ) * 1.0
  25.                 / COUNT(lesson_id) FILTER (
  26.                     WHERE lesson_started_at BETWEEN tutor_approved_date AND COALESCE(adaptation_complete_date, CURRENT_DATE)
  27.                 ),
  28.             0
  29.         ),
  30.         2
  31.     ) AS discipline_in_adaptation
  32. FROM sandbox.dwh_1179_core_tutor_lesson_counter
  33. JOIN mart.tutors USING (tutor_id)
  34. WHERE TRUE = TRUE
  35.     AND tutor_lesson_number_desc IS NOT NULL
  36. GROUP BY tutor_id;
  37.  
  38. --- Отформатированный код из задачи для расчета дисциплины ---
  39. CREATE TEMP TABLE original_discipline AS
  40. WITH needed_lessons AS (
  41.     SELECT
  42.         tutor_id,
  43.         lesson_id,
  44.         lesson_state,
  45.         start_time,
  46.         pupil_id,
  47.         -- Пометим флагом своеврем/несвоеврем отмены и прогулы. Всегда опираемся на статус урока первым делом.
  48.         -- Если статус cancelled и первый отменивший - препод, ставим флаг своевременной отмены.
  49.         COALESCE(lesson_state = 'cancelled' AND cancellation_made_by_role = 'tutor', FALSE)::INT AS is_ok_tutor_cancel,
  50.         -- Если статус прогул П/обоих и есть попытка отмены до начала урока - поздняя отмена преподавателем.
  51.         COALESCE(lesson_state IN ('tutor_no_show', 'both_no_show')
  52.                  AND first_cancellation_datetime < start_time, FALSE)::INT AS is_late_tutor_cancel,
  53.         -- Если статус прогул П/обоих и нет попытки отмены до начала урока - прогул преподавателя.
  54.         COALESCE(lesson_state IN ('tutor_no_show', 'both_no_show')
  55.                  AND (first_cancellation_datetime >= start_time OR first_cancellation_datetime IS NULL), FALSE)::INT AS is_no_tutor_cancel,
  56.         -- Найдем последние 50 уроков преподавателя в любом статусе.
  57.         ROW_NUMBER() OVER (PARTITION BY tutor_id ORDER BY start_time DESC, lesson_id) AS rn_tutor_desc
  58.     FROM
  59.         mart.events_with_lessons
  60.     WHERE
  61.         manager_of_intro_lesson IS FALSE
  62.         AND is_regular_lesson + is_intro_lesson = 1
  63.         AND lesson_state != 'new'
  64.         AND lesson_state IS NOT NULL
  65.         AND is_tetrika_lesson IS TRUE
  66.         AND start_time < '2024-12-01'
  67. ),
  68. -- Посчитаем количество отмен с одним учеником.
  69. finding_cancels_with_same_pupil AS (
  70.     SELECT
  71.         tutor_id,
  72.         lesson_id,
  73.         pupil_id,
  74.         start_time,
  75.         lesson_state,
  76.         -- Найдем количество "плохих" уроков с одним учеником.
  77.         COUNT(lesson_id) OVER (PARTITION BY tutor_id, pupil_id ORDER BY start_time DESC, lesson_id) AS bad_lessons_with_pupil_count
  78.     FROM
  79.         needed_lessons
  80.     WHERE
  81.         (is_ok_tutor_cancel + is_late_tutor_cancel + is_no_tutor_cancel) > 0
  82. ),
  83. all_cancels_together AS (
  84.     SELECT
  85.         needed_lessons.tutor_id,
  86.         needed_lessons.lesson_id,
  87.         needed_lessons.lesson_state,
  88.         needed_lessons.start_time,
  89.         needed_lessons.pupil_id,
  90.         needed_lessons.is_ok_tutor_cancel,
  91.         needed_lessons.is_late_tutor_cancel,
  92.         needed_lessons.is_no_tutor_cancel,
  93.         needed_lessons.rn_tutor_desc,
  94.         -- Где есть информация о прогулах с одним учеником, возьмем её. Где нет - подставим 0.
  95.         COALESCE(finding_cancels_with_same_pupil.bad_lessons_with_pupil_count, 0) AS bad_lessons_with_pupil_count,
  96.         -- Итоговую стоимость каждого прогула рассчитываем так:
  97.         -- своевременная отмена - вес 1, несвоевременная отмена - вес 1.5, прогул - вес 2.
  98.         -- Если несколько плохих уроков с одним учеником, то каждый последующий плохой урок весит больше:
  99.         -- 1-й как 1, второй - как 2, третий - как 3.
  100.         is_ok_tutor_cancel * 1 * COALESCE(finding_cancels_with_same_pupil.bad_lessons_with_pupil_count, 0) +
  101.         is_late_tutor_cancel * 1.5 * COALESCE(finding_cancels_with_same_pupil.bad_lessons_with_pupil_count, 0) +
  102.         is_no_tutor_cancel * 2 * COALESCE(finding_cancels_with_same_pupil.bad_lessons_with_pupil_count, 0) AS final_score
  103.     FROM
  104.         needed_lessons
  105.     LEFT JOIN
  106.         finding_cancels_with_same_pupil USING (lesson_id)
  107. )
  108. SELECT
  109.     tutor_id,
  110.     -- Дисциплина за всё время
  111.     ROUND(
  112.         GREATEST(
  113.             1 - SUM(final_score) * 1.0 / COUNT(lesson_id),
  114.             0
  115.         ),
  116.         2
  117.     ) AS discipline_all_time,
  118.  
  119.     -- Дисциплина за последние 25 уроков
  120.     ROUND(
  121.         GREATEST(
  122.             1 - SUM(final_score) FILTER (WHERE rn_tutor_desc <= 25) * 1.0
  123.                 / COUNT(lesson_id) FILTER (WHERE rn_tutor_desc <= 25),
  124.             0
  125.         ),
  126.         2
  127.     ) AS discipline_25_last_lessons,
  128.  
  129.     -- Дисциплина с даты выпуска до даты окончания адаптации
  130.     ROUND(
  131.         GREATEST(
  132.             1 - SUM(final_score) FILTER (
  133.                 WHERE start_time BETWEEN tutor_approved_date AND COALESCE(adaptation_complete_date, CURRENT_DATE)
  134.             ) * 1.0
  135.                 / COUNT(lesson_id) FILTER (
  136.                     WHERE start_time BETWEEN tutor_approved_date AND COALESCE(adaptation_complete_date, CURRENT_DATE)
  137.                 ),
  138.             0
  139.         ),
  140.         2
  141.     ) AS discipline_in_adaptation
  142. FROM all_cancels_together
  143. JOIN mart.tutors USING (tutor_id)
  144. GROUP BY 1;
  145.  
  146.  
  147. --- Проверяем матчатся ли метрики ---
  148. SELECT
  149.     original_discipline.tutor_id,
  150.     dwh_discipline.tutor_id,
  151.  
  152.     original_discipline.discipline_all_time,
  153.     dwh_discipline.discipline_all_time,
  154.  
  155.     original_discipline.discipline_25_last_lessons,
  156.     dwh_discipline.discipline_25_last_lessons,
  157.  
  158.     original_discipline.discipline_in_adaptation,
  159.     dwh_discipline.discipline_in_adaptation
  160.  
  161. FROM original_discipline
  162. LEFT JOIN dwh_discipline
  163.     ON original_discipline.tutor_id = dwh_discipline.tutor_id
  164. WHERE
  165.     original_discipline.discipline_all_time IS DISTINCT FROM dwh_discipline.discipline_all_time
  166.     OR original_discipline.discipline_25_last_lessons IS DISTINCT FROM dwh_discipline.discipline_25_last_lessons
  167.     OR original_discipline.discipline_25_last_lessons IS DISTINCT FROM dwh_discipline.discipline_25_last_lessons;
  168.  
Advertisement
Add Comment
Please, Sign In to add comment