Advertisement
DefconOne

Длинные рецепты - расчёт "идеального случая" с итогами

Oct 14th, 2023
1,036
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- тройные кавычки для переменных из Питона
  2.  
  3. -- фильтр по дате (раньше 2022.11.01 не имеет смысла смотреть, там не было длинных рецептов)
  4. -- на выходе получаем список id пациентов для дальнейшей работы
  5. WITH id_filter AS
  6.      (SELECT DISTINCT "ИД пациента" AS pac_id
  7.       FROM public.recipes
  8.       WHERE 1 = 1
  9.             AND "Дата выписки рецепта" >= '2022.11.01'
  10.       -- LIMIT 10000
  11.       )
  12.      
  13. -- все записи по найденным id пациентов, пронумерованные окнами по id и ЛП и сгруппированные по ним же
  14.      , detailed AS
  15.        (SELECT r."ИД пациента" AS id_with_1_or_more_long_at_all
  16.                , r."Препарат по МНН"
  17.                , min("Дата выписки рецепта") OVER (PARTITION BY r."ИД пациента"
  18.                                                                 , r."Препарат по МНН") AS min_date
  19.                , max("Дата выписки рецепта") OVER (PARTITION BY r."ИД пациента"
  20.                                                                 , r."Препарат по МНН") AS max_date
  21.                , r."Дата выписки рецепта"
  22.                , r."Длинный/ короткий рецепт"
  23.                , max("Продолжительность применения в дн") AS max_dur
  24.                , DENSE_RANK() OVER (PARTITION BY r."ИД пациента"
  25.                                                  , r."Препарат по МНН"
  26.                                                  ORDER BY r."ИД пациента"
  27.                                                           , r."Препарат по МНН"
  28.                                                           , r."Дата выписки рецепта"
  29.                                                           ) AS num
  30.         FROM public.recipes AS r
  31.         RIGHT JOIN id_filter ON id_filter.pac_id = r."ИД пациента"
  32.         WHERE 1 = 1
  33.               AND doctor_or_paramedic IN ''' + ls_doctor_or_paramedic + '''
  34.               AND mo_type LIKE 'Взрослая'
  35.               AND "Дата выписки рецепта" >= '2022.11.01'
  36.               ''' + ls_is_commented + ''' AND "Препарат по МНН" in ''' + ls_drugs + '''
  37.         GROUP BY r."ИД пациента"
  38.                  , r."Препарат по МНН"
  39.                  , r."Дата выписки рецепта"
  40.                  , r."Длинный/ короткий рецепт"
  41.         ORDER BY r."ИД пациента"
  42.                  , r."Препарат по МНН"
  43.                  , r."Дата выписки рецепта"
  44.                  , r."Длинный/ короткий рецепт"
  45.         -- LIMIT 10000
  46.         )
  47.      
  48. -- добавляем максимальные значения по столбцу с нумерацией
  49. -- и "идеальные" даты, когда у пациентов закончатся лекарства
  50.      , detailed_full AS
  51.        (SELECT *
  52.                , max(num) OVER (PARTITION BY d.id_with_1_or_more_long_at_all
  53.                                             , d."Препарат по МНН"
  54.                                             ) AS max_num
  55.                , max_date::date + max_dur::int - 1 - min_date::date AS date_range
  56.         FROM detailed AS d
  57. -- уберём выброс, который, к тому же, приводит к делению на ноль
  58.         WHERE max_dur::int > 1)
  59.                  
  60. -- фильтруем (есть хотя бы 1 длинный)
  61.      , agg AS
  62.        (SELECT *
  63.         FROM detailed_full AS df
  64.         WHERE 1 = 1
  65.               AND df."Длинный/ короткий рецепт" LIKE 'Длинный'
  66.               -- AND NOT df.num = df.max_num
  67.               )
  68.                  
  69. -- рассчитываем "идеальный случай" (все рецепты - длинные, продолжительности - максимально зафиксированные)
  70.      , ideal_by_drugs AS
  71.        (SELECT id_with_1_or_more_long_at_all as id_pac
  72.                , "Препарат по МНН"
  73.                , min_date
  74.                , date_range
  75.                , max_dur
  76.                , (('today'::date - min_date::date)::int / date_range + 1) AS ideal_n_of_visits
  77.         FROM agg
  78.         GROUP BY id_with_1_or_more_long_at_all
  79.                  , "Препарат по МНН"
  80.                  , min_date
  81.                  , date_range
  82.                  , max_dur)
  83.                  
  84. -- находим суммы визитов за периоды приёма ЛП по пациентам, считаем при этом, что
  85. -- определённые рецепты на ЛП в случае совпадения начальных дат и продолжительностей
  86. -- пациент всё время будет получать в одни и те же дни
  87.      , ideal_agg_sum AS
  88.        (SELECT id_pac
  89.                , sum(ideal_n_of_visits) AS ideal_n_of_visits_sum_by_drugs
  90.        FROM ideal_by_drugs
  91.        GROUP BY id_pac
  92.        ORDER BY sum(ideal_n_of_visits) DESC)
  93.                  
  94. -- строка с агрегированными итогами
  95. SELECT count(id_pac)::text AS id_pac
  96.        -- , avg(ideal_n_of_visits_sum_by_drugs) AS ideal_n_of_visits_sum_by_drugs
  97.        , PERCENTILE_CONT(0.5) WITHIN
  98.          GROUP(ORDER BY ideal_n_of_visits_sum_by_drugs) AS ideal_n_of_visits_sum_by_drugs
  99. FROM ideal_agg_sum
  100.                  
  101. UNION ALL
  102.  
  103. -- вся остальная таблица
  104. SELECT *
  105. FROM ideal_agg_sum
  106.                  
  107. -- далее строим скрипку или ящик с усами по полученному результату
  108. ;
Tags: medicine
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement