每周准备年度工作量,不连续工作两周

时间:2014-10-05 22:09:35

标签: php mysql sql

我们学院有6位评委和4位专家与我们的外宾见面。 4名专家正在与6名法官合作帮助他们。在parent_id列中,每位专家都被证明可以与评委合作。我想逐周准备一份年度工作量表。首先,我准备了一个用户表,显示在下面的捕获中。 (users表)Users 法官和专家不应该连续两周被分配到我想要的位置。所以我编写了一个foreach循环并创建了52周。后来我把名字插入了名字。这是我的代码。

$judge_list = array();
$judge_ids = array();
 // Retrieve all results from users table which mission is judge.
$judges = $db->get_results("SELECT * FROM users WHERE mission='judge'");
// How many times we must repeat to reach 52? Because a year has got 52 weeks.
$repeat =  ceil(52/count($judges)); 
// Until it reaches min. 52 returns first names and last names of the judges. 
for ($i=1; $i<=$repeat; $i++) foreach ($judges as $judge) $judge_list[] = $judge["first_name"] . ' ' . $judge["last_name"];
// Until it reaches min. 52 returns id numbers of the judges. 
for ($i=1; $i<=$repeat; $i++) foreach ($judges as $judge) $judge_ids[] = $judge["id"];
// Make a new array which contains judge's names, surnames and ids. Than get first 52.
$array = array_slice(@array_map(null, $judge_ids, $judge_list), 0, 52);
// Before insert new datas, truncate table.
$db->truncate("scale");
$x = 1;
// And last, insert into annual working scale table.
foreach ($array as $judg){
    $db->insert("scale", array('week' => $x, 'judge_id' => $judg[0], 'judge_name' => $judg[1]));
    $x++;
}

它被认为是下面的捕获。 (scale表)Scale 比我创建了一个专家表,并填写了这样的用户数据。

// Retrieve all results from users table which mission is specialist.
$specialists = $db->get_results("SELECT * FROM users WHERE mission='specialist'");
// Before insert new datas, truncate table.
$db->truncate("project_specialist");
// Loop all specialists.
foreach ($specialists as $specialist) {
    $judges = explode($specialist["parent_id"], ',');
    foreach ($judges as $judge) $db->insert("specialists", array('judge_id' => $judge, 'specialist_id' => $specialist["id"], 'specialist_name' => $specialist["first_name"].' '.$specialist["last_name"])); 
}

就像这样。 (specialist表)Specialists

现在问题是:我想与专家一起更新scale表。专家不应该连续工作两周。但我没有管理。请问你能帮帮我吗,我该如何编写SQL查询代码?

1 个答案:

答案 0 :(得分:1)

这可以通过简单的枚举和模运算符来解决。这种方法没有考虑其他因素,如达到一定水平的专家的工作频率,但这是解决问题的一个开始,无论如何,你似乎正在接近任意枚举。此查询每周返回1行(1-52),并返回一名法官和每周与该法官相关联的单一专家(编辑:并且保证不会在任何级别上连续两周重复同一个人) 。这使用两个独立递增的用户变量来枚举有问题的人,然后通过模运算符(以及专家的parent_id =判断ID)将它们连接到周数的选择。 SQLFiddle example here显示结果。 where子句中的状态和内部查询中使用的计数用于处理大于或小于您提供的样本的数据,并将根据添加或删除(或非 - &#39;活动& #39;状态)此表中的人员。这是假设存在一个表(星期),其中有52行,其中id从1到52.包围和最后左连接是针对奇数情况,当前的判断和专家序列不包括在内。 t匹配,并且第一个序列匹配未能选择专家,因此我们对其进行另一次运行并将第二个结果限制为不在前几周或下一周。在测试台条件下,这提供了52行,每排专家,没有专家或法官连续工作两周。可能需要稍微调整时间表,例如,由于上述奇怪的原因,专家ID 11不能安排工作。

select WeekNum, JudgeID, Judge_first_name, Judge_last_name, coalesce(SpecialistID, s.id) AS SpecialistID, coalesce(Specialist_first_name, s.first_name) AS Specialist_first_name, coalesce(Specialist_last_name, s.last_name) AS Specialist_last_name
from (
    select w.id AS WeekNum, j.id AS JudgeID, j.first_name as Judge_first_name, j.last_name as Judge_last_name
      , s.id As SpecialistID, s.first_name as Specialist_first_name, s.last_name as Specialist_last_name
    from weeks w
      inner join (
        select @judgeNum:=@judgeNum + 1 AS JudgeNum, id, first_name, last_name, (select count(id) from users where mission = 'judge' and status = 'active') AS NumJudges
        from users
          join (select @judgeNum:=0) n
        where mission = 'judge'
          and status = 'active'
      ) j on (w.id % j.NumJudges) + 1 = j.JudgeNum
      left join (
        select SpecialistNum, s.id, cast(substring_index(substring_index(parent_id,',',w.id),',',-1) AS unsigned) AS JudgeID, first_name, last_name, NumSpecialists
        from (
            select @specialistNum:=@specialistNum + 1 AS SpecialistNum, id, parent_id, first_name, last_name, (select count(id) from users where mission = 'specialist' and status = 'active') AS NumSpecialists
            from users
              join (select @specialistNum:=0) n
            where mission = 'specialist'
              and status = 'active'
          ) s
          join weeks w on w.id <= length(s.parent_id) - length(replace(s.parent_id,',','')) + 1
      ) s on s.JudgeID = j.id
        and (w.id % s.NumSpecialists) + 1 = s.SpecialistNum
    ) t
    left join (
        select *
        from users u
        where mission = 'specialist'
            and status = 'active'
    ) s on t.specialistID IS NULL
        AND s.parent_id rlike '/[^\d]' + t.JudgeID + '[^\d]/'
where s.id is null or s.id not in (
    select c.id As SpecialistID
    from weeks w2
        inner join (
            select @judgeNum:=@judgeNum + 1 AS JudgeNum, id, first_name, last_name, (select count(id) from users where mission = 'judge' and status = 'active') AS NumJudges
            from users
              join (select @judgeNum:=0) n
            where mission = 'judge'
                and status = 'active'
        ) j on (w2.id % j.NumJudges) + 1 = j.JudgeNum
        left join (
            select SpecialistNum, c.id, cast(substring_index(substring_index(parent_id,',',w3.id),',',-1) AS unsigned) AS JudgeID, first_name, last_name, NumSpecialists
            from (
                select @specialistNum:=@specialistNum + 1 AS SpecialistNum, id, parent_id, first_name, last_name, (select count(id) from users where mission = 'specialist' and status = 'active') AS NumSpecialists
                from users
                  join (select @specialistNum:=0) n
                where mission = 'specialist'
                  and status = 'active'
              ) c
              join weeks w3 on w3.id <= length(c.parent_id) - length(replace(c.parent_id,',','')) + 1
        ) c on c.JudgeID = j.id
        and (w2.id % c.NumSpecialists) + 1 = c.SpecialistNum
    where w2.id in (t.WeekNum-1, t.WeekNum+1)
)
order by weeknum
;