php - 每周编制年度工作规模,无需连续工作两周

标签 php mysql sql

有6位评委和4位专家在我们学院会见外宾。 4 位专家与 6 位评委一起为他们提供帮助。在 parent_id 列中,显示与评委合作过的每位专家。我想每周准备一份年度工作量表。因此,首先我准备了一个用户表,如下图所示。 (用户 表)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 然后我创建了一个专家表并填充了这样的用户数据。

// 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"])); 
}

原来是这样的。 (专家表)Specialists

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

最佳答案

这可以通过简单的枚举和模运算符来解决。这种方法没有考虑其他因素,例如达到一定水平的专家的工作频率,但这是解决问题的一个开始,无论如何,您似乎都是通过任意枚举的方式来解决这个问题的。此查询每周返回 1 行 (1-52),并每周返回一位法官和与该法官链接的一位专家(编辑:并且保证不会在任一级别上连续两周重复同一个人) 。这利用了两个独立递增的用户变量来枚举相关人员,然后通过模运算符(以及parent_id =专家的法官id)将它们加入到周数的选择中。 SQLFiddle example here显示结果。 where子句中的状态和内部查询中使用的计数是为了处理大于或小于您给出的样本的数据而构建的,并且会根据添加或删除(或非“事件”状态)自动调整调度这张表中的人。这是假设存在一个有 52 行的表(周),其中 id 从 1 到 52。封装和最终左连接用于当前法官和专家序列不匹配的奇怪情况,并且第一次序列匹配未能选择专家,因此我们再次运行它,并将第二个结果限制为不在之前或之后几周内。在测试台条件下,这提供了 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
;

关于php - 每周编制年度工作规模,无需连续工作两周,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26207721/

相关文章:

php - 在 MySQL 中执行查询的性能。也许正在使用缓存?

mysql - 按组获取前 10 名值(value)

mysql - Redis : Is it possible to get filtered data by any field stored in Redis?

sql - 在 Postgres 函数中使用 WHERE ... IN

php - Google Maps JavaScript API V3 不适用于本地主机

php - 无法通过 PHP 执行 CLI 命令

php - 删除 PHP 中的查询字符串(有时基于引用者)

php - 加入 MySql 表和 SUM

MySQL 更改同一外键的两列

php - 如何从数据库中获取特定行?