Php 我们如何将员工的职责随机化

Php 我们如何将员工的职责随机化,php,mysql,Php,Mysql,我正试着允许三班倒 存在以下约束: 1st shift will have 5 employee >2nd shift will have 3 employee 3rd shift will have 2 employee 如果一个人在任何班次中被分配了工作,他将不被允许再工作两个班次。例如,如果X先生在8月3日的第二班被分配了工作,那么他既不会在8月3日的第三班也不会在8月4日的第一班中得到工作 我已经使用rand函数随机选择了员工。我面临约束4的问题。i、 e.我如何确保在第一班

我正试着允许三班倒

存在以下约束:

1st shift will have 5 employee 
>2nd shift will have 3 employee
3rd shift will have 2 employee 
如果一个人在任何班次中被分配了工作,他将不被允许再工作两个班次。例如,如果X先生在8月3日的第二班被分配了工作,那么他既不会在8月3日的第三班也不会在8月4日的第一班中得到工作

我已经使用rand函数随机选择了员工。我面临约束4的问题。i、 e.我如何确保在第一班被分配的员工不会在第二班或第三班被分配

我的MySQL查询是:

SELECT * FROM `employee` ORDER BY rand()

因为您没有提供太多的细节,所以很难弄清楚如何在数据库中存储信息。我想以下问题将适合您的情况:

SELECT * FROM employee e
WHERE e.employee_id NOT IN (
                            SELECT es.employee_id FROM emp_shifts es
                            WHERE shift IN (...)
                            )
ORDER BY RAND()
我假设您正在emp_班次表中存储班次分配。
... 是您要排除的最后两个班次。

我认为这是一个很难用SQL解决的问题,但如果我要尝试,我可能会从随机分配员工开始

DROP TABLE IF EXISTS employees;

CREATE TABLE employees 
(employee_id SERIAL PRIMARY KEY);

INSERT INTO employees VALUES
(101),(102),(103),(104),(105),(106),(107),(108),(109),(110);

SELECT employee_id,@i:=@i+1 i FROM (SELECT employee_id FROM employees ORDER BY RAND()) x,(SELECT @i:=0) vars;
+-------------+------+
| employee_id | i    |
+-------------+------+
|         108 |    1 |
|         109 |    2 |
|         110 |    3 |
|         103 |    4 |
|         105 |    5 |
|         106 |    6 |
|         102 |    7 |
|         104 |    8 |
|         107 |    9 |
|         101 |   10 |
+-------------+------+
现在,只要我们有至少3天的员工5+3+2=10,我们就可以循环浏览列表,并且知道每个员工在每个工作日之间都会有至少两个连续的休息日

下面是关于这个问题的另一个方面的想法

DROP TABLE IF EXISTS shifts;

CREATE TABLE shifts 
(shift_id SERIAL PRIMARY KEY
,shift_size INT NOT NULL
);

INSERT INTO shifts VALUES
(1,5),(2,3),(3,2),(4,3),(5,2);

SELECT shift_id
     , ROUND(COALESCE(@j:=@prev+1,1),0) range_start
     , range_end, @prev:=range_end 
  FROM 
     ( SELECT x.*
            , SUM(y.shift_size) range_end 
         FROM shifts x 
         JOIN shifts y 
           ON y.shift_id <= x.shift_id 
        GROUP 
           BY x.shift_id
     ) b
     , ( SELECT @j:=1,@prev:=null) vars
 ORDER 
    BY shift_id;
+----------+-------------+-----------+------------------+
| shift_id | range_start | range_end | @prev:=range_end |
+----------+-------------+-----------+------------------+
|        1 |           1 |         5 |                5 |
|        2 |           6 |         8 |                8 |
|        3 |           9 |        10 |               10 |
|        4 |          11 |        13 |               13 |
|        5 |          14 |        15 |               15 |
+----------+-------------+-----------+------------------+
现在你有了一个雇员序列id和一个范围,这些id可以在这个范围内。范围大于员工列表,因此必须使用员工表的大小作为范围的模数

 SELECT a.shift_id
      , MOD(a.range_start-1,(SELECT COUNT(*) FROM employees))+1 range_start
      , MOD(a.range_end-1,(SELECT COUNT(*) FROM employees))+1 range_end
   FROM
      ( SELECT shift_id
      , ROUND(COALESCE(@j:=@prev+1,1),0) range_start
      , range_end, @prev:=range_end
   FROM
      ( SELECT x.*
             , SUM(y.shift_size) range_end
          FROM shifts x
          JOIN shifts y
            ON y.shift_id <= x.shift_id
         GROUP
            BY x.shift_id
      ) b
      , ( SELECT @j:=1,@prev:=null) vars
  ORDER
     BY shift_id
     ) a
   ORDER BY shift_id;
+----------+-------------+-----------+
| shift_id | range_start | range_end |
+----------+-------------+-----------+
|        1 |           1 |         5 |
|        2 |           6 |         8 |
|        3 |           9 |        10 |
|        4 |           1 |         3 |
|        5 |           4 |         5 |
+----------+-------------+-----------+

我想我可以把最后一步留给读者作为练习。

尝试使用php并与usSee分享您是如何存储轮班分配详细信息的?请提供SQLFIDLE,以便我提供更好的解决方案。