随机分配工作位置和每个位置应不超过指定的员工数量(Randomly assign work loca

2019-07-31 19:26发布

我想的地点列表中选择员工的独特乱张贴/招聘的地方,所有的员工都已经张贴在这些地方,我想为他们生成一个新的随机刊登场所使用“其中”条件“员工新随机位置会不等于他们的家的地方,与他们的指定randomnly选择员工必须小于或等于将来自地方台明智的指定号码“

Employee表是:

EmpNo   EmpName           CurrentPosting    Home        Designation   RandomPosting
1       Mac               Alabama           Missouri      Manager       
2       Peter             California        Montana       Manager       
3       Prasad            Delaware          Nebraska      PO       
4       Kumar             Indiana           Nevada        PO       
5       Roy               Iowa              New Jersey    Clerk       

等等...

而地方台(含员工数量地名 - 指定明智的)是: -

PlaceID  PlaceName      Manager     PO    Clerk
1        Alabama           2        0     1
2        Alaska            1        1     1
3        Arizona           1        0     2
4        Arkansas          2        1     1
5        California        1        1     1
6        Colorado          1        1     2
7        Connecticut       0        2     0

等等...

试图与NEWID()像如下,并能够与RandomPosting地名来选择员工,

WITH cteCrossJoin AS (
SELECT e.*, p.PlaceName AS RandomPosting,
       ROW_NUMBER() OVER(PARTITION BY e.EmpNo ORDER BY NEWID()) AS RowNum
    FROM Employee e
        CROSS JOIN  Place p
    WHERE e.Home <> p.PlaceName
)
SELECT *
FROM cteCrossJoin
WHERE RowNum = 1;

另外我需要限制在指定的数字基础(以地方台)的随机选择......这是分配每个员工地名(从地方)随机其不等于CurrentPosting和家庭(以员工)和地点明智指定将不超过给出的数字。

提前致谢。

Answer 1:

也许是这样的:

select C.* from 
(
    select *, ROW_NUMBER() OVER(PARTITION BY P.PlaceID, E.Designation ORDER BY NEWID()) AS RandPosition
        from Place as P cross join Employee E
    where P.PlaceName != E.Home AND P.PlaceName != E.CurrentPosting
) as C
where 
    (C.Designation = 'Manager' AND C.RandPosition <= C.Manager) OR
    (C.Designation = 'PO' AND C.RandPosition <= C.PO) OR
    (C.Designation = 'Clerk' AND C.RandPosition <= C.Clerk)

这应该尝试匹配随意根据自己指定丢弃相同currentPosting和家庭的员工,而不是分配比是在为指定的每一列指定了。 然而,这可能会返回相同的员工对几个地方,因为它们可根据该标准匹配多个。


编辑:看到关于没有需要一个高性能的单一查询来解决这个问题(这我不知道,甚至有可能),以及您的评论后,因为它似乎更多的是“一次性”的过程中,你将调用,我使用光标和一个临时表来解决你的作业的问题写了下面的代码:

select *, null NewPlaceID into #Employee from Employee

declare @empNo int
DECLARE emp_cursor CURSOR FOR  
SELECT EmpNo from Employee order by newid()

OPEN emp_cursor   
FETCH NEXT FROM emp_cursor INTO @empNo

WHILE @@FETCH_STATUS = 0   
BEGIN
    update #Employee 
    set NewPlaceID = 
        (
        select top 1 p.PlaceID from Place p 
        where 
            p.PlaceName != #Employee.Home AND 
            p.PlaceName != #Employee.CurrentPosting AND
            (
                CASE #Employee.Designation 
                WHEN 'Manager' THEN p.Manager
                WHEN 'PO' THEN p.PO
                WHEN 'Clerk' THEN p.Clerk
                END
            ) > (select count(*) from #Employee e2 where e2.NewPlaceID = p.PlaceID AND e2.Designation = #Employee.Designation)
        order by newid()
        ) 
    where #Employee.EmpNo = @empNo
    FETCH NEXT FROM emp_cursor INTO @empNo   
END

CLOSE emp_cursor
DEALLOCATE emp_cursor

select e.*, p.PlaceName as RandomPosting from Employee e
inner join #Employee e2 on (e.EmpNo = e2.EmpNo)
inner join Place p on (e2.NewPlaceID = p.PlaceID)

drop table #Employee

其基本思路是,它遍历的员工,以随机顺序,并分配给每一个满足不同家庭和目前发布的标准,以及控制这会被分配给各地方,各指定量的随机地点以确保该位置是不是“过度分配的”为每个角色。

这段代码实际上没有改变,虽然你的数据。 最终的SELECT语句只返回所提出的任务。 然而,你可以很容易地改变它,使您的实际变化Employee相应表格。



Answer 2:

我假设约束条件是:

  • 一个员工不能去到相同位置的S /目前他所在。
  • 所有网站必须在每个类别中,如雇员,预计至少有一名雇员。

最重要的理念是要认识到你是不是在找一个“随机”分配。 您正在寻找位置的置换,如有条件,每个人都移到别的地方去。

我会形容为管理者的答案。 你可能会想为每种类型员工的三个查询。

其核心思想是ManagerPositions表。 这有一个地方,一个序列号,并在场所内的序列号。 以下是一个例子:

Araria     1    1
Araria     2    2
Arwal      1    3
Arungabad  1    4

该查询通过连接到INFORMATION_SCHEMA.COLUMNS与ROW_NUMBER()函数来分配序列创建该表。 这是一个快速和肮脏的方式来获得SQL Server中的序列 - 但只要完全有效的,因为你需要的最大数量(即在任何一个位置管理人员的最大数量)小于列的数量数据库。 还有其他的方法来处理更一般的情况。

接下来的关键思想是旋转的地方,而不是随机选择它们。 它使用的想法从模运算 - 加一个偏移量,并采取过立场的总数剩余部分。 最后的查询看起来是这样的:

with ManagerPositions as (
     select p.*,
            row_number() over (order by placerand, posseqnum) as seqnum,
            nums.posseqnum
     from (select p.*, newid() as placerand
           from places p
          ) p join
          (select row_number() over (order by (select NULL)) as posseqnum
           from INFORMATION_SCHEMA.COLUMNS c
          ) nums
          on p.Manager <= nums.posseqnum
    ),
   managers as (
    select e.*, mp.seqnum
    from (select e.*,
                 row_number() over (partition by currentposting order by newid()
                                   ) as posseqnum
          from Employees e              
          where e.Designation = 'Manager'
         ) e join
         ManagerPositions mp
         on e.CurrentPosting = mp.PlaceName and
            e.posseqnum = mp.posseqnum
  )
select m.*, mp.PlaceId, mp.PlaceName
from managers m cross join
     (select max(seqnum) as maxseqnum, max(posseqnum) as maxposseqnum
      from managerPositions mp
     ) const join
     managerPositions mp
     on (m.seqnum+maxposseqnum+1) % maxseqnum + 1 = mp.seqnum

好吧,我知道这是复杂的。 你必须为每个经理的职位表(不计在你的声明,其对每个位置的行很重要)。 有两种方法来标识的位置。 第一种是通过地方和地方(posseqnum)内的计数。 第二个是通过对行的增量编号。

发现在表中的每个经理的当前位置。 这应该是唯一的,因为我考虑到在每个地方管理人员的数量。 然后,加一个偏移量的位置,并分配到位。 通过使偏移比maxseqnum越大,管理者是保证移动到另一个位置(除了在不寻常的边界的情况下,其中一个位置具有一半以上的经理)。

如果目前所有的经理职位填满,那么这保证了所有会移动到下一个位置。 由于ManagerPositions使用分配SEQNUM随机ID,“下”的地方是随机的,而不是由旁边ID或字母。

该解决方案确实有很多员工一起前往同一新的位置。 您可以通过在试图表达比“1”,其他值有所解决这个问题(m.seqnum+maxposseqnum+1)

我认识到,没有改变这一点,以防止目前地点和下一个地方之间的关系的一种方式。 这将执行以下操作:

  1. 分配SEQNUM随机ManagerPosition
  2. 在表中比较不同的偏移量,通过的时间在表中的两个位置,通过分离偏移的数目来评价每部,是相同的。
  3. 选择具有最小等级(其优选为0)的偏移量。
  4. 使用最终匹配子句中的偏移。

我没有足够的时间,现在写这个的SQL。



文章来源: Randomly assign work location and each location should not exceed the number of designated employees