Question
How do I modify my SQL Statement so each Project has 4 unique judges and each Judge evenly judges the same number of projects for their assigned division and category?
Requirements
Population Project needs to be reviewed by Population Judge (x) times. x = 4
- Each Project is grouped by Division and Category.
Each Judge is grouped by Division and Category.
Each Project must be reviewed by (x) unique Judges.
- Each Judge should never review the same project twice.
- Each Judge should be assigned an equal number of projects to review as the other judges in their division and category grouping.
Sample Source Judge Table
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 );
Sample Source Project Table
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 Code
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
Data Output Example
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
Problem
The number of count(*)/projects should be distributed evenly among the Division and Category for a pool a judge. Instead, some judges are assigned to 20 projects while others are assigned to very few. I don’t know how to modify my query so each judge must be reference an equal number of times amongst the Project Division and Category grouping. I want to ensure equal participation.
JUDGE_ID COUNT(*) 64 8 72 16 23 20 57 4 14 4 6 4 58 9
Advertisement
Answer
I came up with a solution utilizing procedures in my Oracle database.
My approach was to loop through each project id. While inside my loop it would loop 1 to the number of assignments I required, in this case, 4.
We needed to pull out a random judge id from a list of judges by a count of how many assignments they have already been given in ascending order. I wanted to use the lowest number of assignments first.
Their assignment count if bumped +1
We update the values in the final list table
We loop until the number of assignments by project is given and then the next project is assessed.
create or replace procedure random_judge_project_list as
assign_count number := 0; next_count number := 1; assignments number := 4; jid number; sql_stmt varchar2(4000); location varchar2(20);
begin
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;
end;