Как я могу изменить свое SQL Заявление, чтобы в каждом Проекте было (x) Судей, и каждый Судья участвовал равномерно среди своего населения? - PullRequest
2 голосов
/ 18 февраля 2020

Вопрос

Как мне изменить мое SQL утверждение, чтобы в каждом проекте было 4 уникальных судьи, и каждый судья равномерно оценивал одинаковое количество проектов для назначенного им подразделения и категории?

Требования

Проект по народонаселению должен быть рассмотрен судьей по народонаселению (x) раз. x = 4

  • Каждый проект сгруппирован по отделам и категориям.
  • Каждый судья сгруппирован по отделам и категориям.

  • Каждый проект должен быть рассмотрен (x) уникальными судьями.

  • Каждый судья никогда не должен рассматривать один и тот же проект дважды.
  • Каждому судье должно быть назначено равное количество проектов для рассмотрения. как другие судьи в их подразделениях и категориях.

Таблица исходных судей

create table judges(judge_id, division, category) as (
    select 68, 'Elementary', 'ANY' from dual union all
    select 19, 'Elementary', 'ANY' from dual union all
    select 22, 'Elementary', 'ANY' from dual union all
    select 32, 'Elementary', 'ANY' from dual union all
    select 33, 'Elementary', 'ANY' from dual union all
    select 37, 'Elementary', 'ANY' from dual union all
    select 38, 'Elementary', 'ANY' from dual union all
    select 40, 'Elementary', 'ANY' from dual union all
    select 47, 'Elementary', 'ANY' from dual union all
    select 62, 'Elementary', 'ANY' from dual union all
    select 63, 'Elementary', 'ANY' from dual union all
    select 13, 'Elementary', 'ANY' from dual union all
    select 36, 'Elementary', 'ANY' from dual union all
    select 55, 'Elementary', 'ANY' from dual union all
    select 59, 'Elementary', 'ANY' from dual union all
    select 60, 'Elementary', 'ANY' from dual union all
    select 9, 'Junior', 'EC' from dual union all
    select 10, 'Junior', 'EC' from dual union all
    select 48, 'Junior', 'EC' from dual union all
    select 11, 'Junior', 'LS' from dual union all
    select 21, 'Junior', 'LS' from dual union all
    select 23, 'Junior', 'LS' from dual union all
    select 26, 'Junior', 'LS' from dual union all
    select 31, 'Junior', 'LS' from dual union all
    select 80, 'Junior', 'LS' from dual union all
    select 14, 'Junior', 'PE' from dual union all
    select 15, 'Junior', 'PE' from dual union all
    select 24, 'Junior', 'PE' from dual union all
    select 29, 'Junior', 'PE' from dual union all
    select 30, 'Junior', 'PE' from dual union all
    select 43, 'Junior', 'PE' from dual union all
    select 53, 'Junior', 'PE' from dual union all
    select 56, 'Junior', 'PE' from dual union all
    select 57, 'Junior', 'PE' from dual union all
    select 58, 'Junior', 'PE' from dual union all
    select 65, 'Junior', 'PE' from dual union all
    select 67, 'Junior', 'PE' from dual union all
    select 69, 'Junior', 'PE' from dual union all
    select 8, 'Senior', 'ANY' from dual union all
    select 18, 'Senior', 'ANY' from dual union all
    select 20, 'Senior', 'ANY' from dual union all
    select 35, 'Senior', 'ANY' from dual union all
    select 66, 'Senior', 'ANY' from dual union all
    select 39, 'Senior', 'ANY' from dual union all
    select 70, 'Senior', 'ANY' from dual union all
    select 71, 'Senior', 'ANY' from dual union all
    select 74, 'Senior', 'ANY' from dual union all
    select 6, 'Senior', 'ANY' from dual union all
    select 44, 'Senior', 'ANY' from dual union all
    select 45, 'Senior', 'ANY' from dual union all
    select 49, 'Senior', 'ANY' from dual union all
    select 61, 'Senior', 'ANY' from dual union all
    select 64, 'Senior', 'ANY' from dual union all
    select 72, 'Senior', 'ANY' from dual union all
    select 75, 'Senior', 'ANY' from dual union all
    select 79, 'Senior', 'ANY' from dual union all
    select 82, 'Senior', 'ANY' from dual
);

Таблица исходных проектов

create table projects(project_id, division, category) as (
     select 39, 'Elementary', 'ANY' from dual union all
    select 40, 'Elementary', 'ANY' from dual union all
    select 47, 'Elementary', 'ANY' from dual union all
    select 48, 'Elementary', 'ANY' from dual union all
    select 56, 'Elementary', 'ANY' from dual union all
    select 57, 'Elementary', 'ANY' from dual union all
    select 58, 'Elementary', 'ANY' from dual union all
    select 60, 'Elementary', 'ANY' from dual union all
    select 65, 'Elementary', 'ANY' from dual union all
    select 66, 'Elementary', 'ANY' from dual union all
    select 93, 'Elementary', 'ANY' from dual union all
    select 94, 'Elementary', 'ANY' from dual union all
    select 97, 'Elementary', 'ANY' from dual union all
    select 104, 'Elementary', 'ANY' from dual union all
    select 105, 'Elementary', 'ANY' from dual union all
    select 107, 'Elementary', 'ANY' from dual union all
    select 110, 'Elementary', 'ANY' from dual union all
    select 112, 'Elementary', 'ANY' from dual union all
    select 114, 'Elementary', 'ANY' from dual union all
    select 117, 'Elementary', 'ANY' from dual union all
    select 120, 'Elementary', 'ANY' from dual union all
    select 121, 'Elementary', 'ANY' from dual union all
    select 123, 'Elementary', 'ANY' from dual union all
    select 124, 'Elementary', 'ANY' from dual union all
    select 126, 'Elementary', 'ANY' from dual union all
    select 127, 'Elementary', 'ANY' from dual union all
    select 128, 'Elementary', 'ANY' from dual union all
    select 133, 'Elementary', 'ANY' from dual union all
    select 134, 'Elementary', 'ANY' from dual union all
    select 136, 'Elementary', 'ANY' from dual union all
    select 140, 'Elementary', 'ANY' from dual union all
    select 142, 'Elementary', 'ANY' from dual union all
    select 152, 'Elementary', 'ANY' from dual union all
    select 153, 'Elementary', 'ANY' from dual union all
    select 162, 'Elementary', 'ANY' from dual union all
    select 167, 'Elementary', 'ANY' from dual union all
    select 173, 'Elementary', 'ANY' from dual union all
    select 174, 'Elementary', 'ANY' from dual union all
    select 188, 'Elementary', 'ANY' from dual union all
    select 27, 'Junior', 'EC' from dual union all
    select 67, 'Junior', 'EC' from dual union all
    select 82, 'Junior', 'EC' from dual union all
    select 83, 'Junior', 'EC' from dual union all
    select 99, 'Junior', 'EC' from dual union all
    select 113, 'Junior', 'EC' from dual union all
    select 115, 'Junior', 'EC' from dual union all
    select 149, 'Junior', 'EC' from dual union all
    select 164, 'Junior', 'EC' from dual union all
    select 169, 'Junior', 'EC' from dual union all
    select 185, 'Junior', 'EC' from dual union all
    select 189, 'Junior', 'EC' from dual union all
    select 18, 'Junior', 'LS' from dual union all
    select 19, 'Junior', 'LS' from dual union all
    select 20, 'Junior', 'LS' from dual union all
    select 21, 'Junior', 'LS' from dual union all
    select 23, 'Junior', 'LS' from dual union all
    select 24, 'Junior', 'LS' from dual union all
    select 26, 'Junior', 'LS' from dual union all
    select 28, 'Junior', 'LS' from dual union all
    select 29, 'Junior', 'LS' from dual union all
    select 30, 'Junior', 'LS' from dual union all
    select 78, 'Junior', 'LS' from dual union all
    select 80, 'Junior', 'LS' from dual union all
    select 90, 'Junior', 'LS' from dual union all
    select 91, 'Junior', 'LS' from dual union all
    select 106, 'Junior', 'LS' from dual union all
    select 144, 'Junior', 'LS' from dual union all
    select 150, 'Junior', 'LS' from dual union all
    select 151, 'Junior', 'LS' from dual union all
    select 156, 'Junior', 'LS' from dual union all
    select 157, 'Junior', 'LS' from dual union all
    select 159, 'Junior', 'LS' from dual union all
    select 161, 'Junior', 'LS' from dual union all
    select 165, 'Junior', 'LS' from dual union all
    select 166, 'Junior', 'LS' from dual union all
    select 168, 'Junior', 'LS' from dual union all
    select 178, 'Junior', 'LS' from dual union all
    select 180, 'Junior', 'LS' from dual union all
    select 187, 'Junior', 'LS' from dual union all
    select 22, 'Junior', 'PE' from dual union all
    select 59, 'Junior', 'PE' from dual union all
    select 61, 'Junior', 'PE' from dual union all
    select 74, 'Junior', 'PE' from dual union all
    select 81, 'Junior', 'PE' from dual union all
    select 95, 'Junior', 'PE' from dual union all
    select 96, 'Junior', 'PE' from dual union all
    select 116, 'Junior', 'PE' from dual union all
    select 145, 'Junior', 'PE' from dual union all
    select 148, 'Junior', 'PE' from dual union all
    select 158, 'Junior', 'PE' from dual union all
    select 160, 'Junior', 'PE' from dual union all
    select 172, 'Junior', 'PE' from dual union all
    select 176, 'Junior', 'PE' from dual union all
    select 181, 'Junior', 'PE' from dual union all
    select 186, 'Junior', 'PE' from dual union all
    select 14, 'Senior', 'ANY' from dual union all
    select 15, 'Senior', 'ANY' from dual union all
    select 42, 'Senior', 'ANY' from dual union all
    select 43, 'Senior', 'ANY' from dual union all
    select 44, 'Senior', 'ANY' from dual union all
    select 45, 'Senior', 'ANY' from dual union all
    select 46, 'Senior', 'ANY' from dual union all
    select 49, 'Senior', 'ANY' from dual union all
    select 51, 'Senior', 'ANY' from dual union all
    select 52, 'Senior', 'ANY' from dual union all
    select 53, 'Senior', 'ANY' from dual union all
    select 54, 'Senior', 'ANY' from dual union all
    select 75, 'Senior', 'ANY' from dual union all
    select 76, 'Senior', 'ANY' from dual union all
    select 77, 'Senior', 'ANY' from dual union all
    select 92, 'Senior', 'ANY' from dual union all
    select 108, 'Senior', 'ANY' from dual union all
    select 118, 'Senior', 'ANY' from dual union all
    select 119, 'Senior', 'ANY' from dual union all
    select 125, 'Senior', 'ANY' from dual union all
    select 131, 'Senior', 'ANY' from dual union all
    select 132, 'Senior', 'ANY' from dual union all
    select 135, 'Senior', 'ANY' from dual union all
    select 137, 'Senior', 'ANY' from dual union all
    select 138, 'Senior', 'ANY' from dual union all
    select 139, 'Senior', 'ANY' from dual union all
    select 141, 'Senior', 'ANY' from dual union all
    select 143, 'Senior', 'ANY' from dual union all
    select 146, 'Senior', 'ANY' from dual union all
    select 154, 'Senior', 'ANY' from dual union all
    select 171, 'Senior', 'ANY' from dual
);

Oracle SQL Код

select 
     project_id
    ,division
    ,category
    ,judge_id
    ,best_match
from(
    select 
         project.project_id
        ,project.division
        ,project.category
        ,judge.judge_id
        ,row_number() over(
            partition by project.project_id 
            order by dbms_random.value
        ) as best_match
    from frsf_fair.project_division_category project
    left join (
        select 
            judge_id
            ,division
            ,category
            ,row_number() over(
                partition by division 
                order by dbms_random.value
            ) as r
        from frsf_fair.judge_division_category
        ) judge on project.division = judge.division 
            and project.category = judge.category   
) assignment
where best_match <= 4

Пример вывода данных

PROJECT_ID  DIVISION    CATEGORY    JUDGE_ID    BEST_MATCH
14  Senior  ANY 72  1
14  Senior  ANY 74  2
14  Senior  ANY 20  3
14  Senior  ANY 44  4

15  Senior  ANY 79  1
15  Senior  ANY 39  2
15  Senior  ANY 75  3
15  Senior  ANY 20  4

18  Junior  LS  23  1
18  Junior  LS  31  2
18  Junior  LS  26  3
18  Junior  LS  21  4

Задача

Количество (*) / проектов должно быть равномерно распределено между Отделом и категорией для пул судья. Вместо этого, некоторые судьи назначены на 20 проектов, а другие назначены очень немногим. Я не знаю, как изменить свой запрос, поэтому каждый судья должен ссылаться равное количество раз в подразделении проекта и в категории. Я хочу обеспечить равное участие.

JUDGE_ID    COUNT(*)
64  8
72  16
23  20
57  4
14  4
6   4
58  9

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Я нашел решение, использующее процедуры в моей базе данных Oracle.

Мой подход состоял в том, чтобы l oop через каждый идентификатор проекта. Находясь внутри моего l oop, я получу l oop 1 до количества назначений, которое мне требуется, в данном случае 4.

  1. Нам нужно было вытащить случайный идентификатор судьи из список судей по количеству заданий, которые им уже даны в порядке возрастания. Сначала я хотел использовать наименьшее количество назначений.

  2. Количество назначений при увеличении + 1

  3. Мы обновляем значения в окончательном списке таблица

  4. Мы l oop до тех пор, пока не будет задано количество назначений по проекту, а затем не будет оценен следующий проект.

    создайте или замените процедуру random_judge_project_list как

    assign_count    number := 0;
    next_count      number := 1;
    
    assignments     number := 4;
    jid             number;
    sql_stmt         varchar2(4000);
    
    location varchar2(20);
    

    начало

    execute immediate 'truncate table judge_project_list';
    execute immediate 'update judge_assignment_count set assignment_count = 0';
    
    /*We First Need to Loop through Each Project*/
    for project in (
        select 
            project_id
            ,division
            ,category as source_category
            ,case division 
                when 'Junior' then category
                else 'ANY'
            end as category      
        from projects a
        order by division asc, category asc
    )
    loop
        /*While Looping we then need to assign judges randomly*/   
        for assign in 1 .. assignments
        loop
    
                select judge_id
                into jid
                from(
                    select *
                    from judge_assignment_count
                    where division = project.division
                        and judge_id not in (select judge_id from judge_project_list where project_id = project.project_id)
                    order by assignment_count asc, dbms_random.random asc
                ) where rownum = 1
            ;
    
            select assignment_count
            into assign_count
            from judge_assignment_count
            where judge_id = jid 
            and rownum = 1
            ;
    
            next_count := assign_count + 1;
    
            --dbms_output.put_line(sql_stmt);
    
            --execute immediate sql_stmt into jid;
    
            insert into judge_project_list (project_id, judge_id, division, category) values (project.project_id, jid, project.division, project.category);
    
            execute immediate 'update judge_assignment_count set assignment_count = ' || next_count || ' where judge_id = ' || jid;
    
    
    
        end loop;
    
    end loop;
    
    commit;
    

    конец;

0 голосов
/ 18 февраля 2020

Лучшее, что я мог сделать, это запрос:

with 
  t as (select judge_id jid, project_id pid, category cat, division div, 
               dense_rank() over (order by project_id) rp,
               dense_rank() over (order by judge_id) rj,
               count(1) over (partition by project_id) cnt
          from judges join projects using (division, category)),
  c(pid, jid, cat, div, rn, rp) as (
    select pid, jid, cat, div, 1, rp from t where mod(rp, cnt) = mod(rj, cnt)
    union all
    select c.pid, t.jid, c.cat, c.div, rn + 1, c.rp
      from c join t on c.rp = t.rp and c.jid <> t.jid 
                   and mod(t.rp, t.cnt) = mod(t.rj + c.rn, t.cnt) 
      where rn < 3)
select * from c 

Что он делает? Сначала объединяется c с добавленными номерами строк и счетами (rp, rj, cnt). Эти столбцы затем используются mod() для объединения строк в запросе привязки where mod(rp, cnt) = mod(rj, cnt). Затем рекурсивная часть, которая только добавляет необходимое количество судей к каждому проекту. Возможно, кто-то может сделать это без рекурсии, но я не смог. Вы можете несколько рандомизировать вывод, назначая судьям случайные id с и используя их в запросе вместо реальных id с. Замените 3 необходимым количеством отзывов.

Это dbfiddle показывает 5 проектов, 5 судей, 3 отзыва на проект. Судьи не повторяются, распределяются поровну.


Редактировать: Исправлен основной запрос c:

with t as ( 
    select category, division, project_id, judge_id,
           dense_rank() over (partition by category, division 
                              order by project_id) rp,
           dense_rank() over (partition by category, division, project_id 
                              order by judge_id) rj,
           count(1) over (partition by project_id) cnt
      from projects join judges using (category, division) ) 
select * from t
  join (select level lvl from dual connect by level <= 3) 
    on mod(rj, cnt) =  mod((rp -1) * 3 + lvl, cnt) 

Я проверил результаты для проектов ( group by project_id) и каждый проект имеет 3 разных судей. Я проверил результаты для судей (группа по категориям, подразделение, jud_id) и каждый судья в своем классе имеет одинаковое количество дел (отличается на единицу, если для равного распределения недостаточно проектов).

Лог c такой же, как в моем первом запросе. Как я уже сказал, вы можете сначала рандомизировать судей:

select row_number() over (order by dbms_random.value) rnd_jdg_id, judges.* from judges

и использовать этот поддельный идентификатор в качестве входных данных в основном запросе, чтобы получить полностью случайное назначение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...