我试图在一个地方列表中选择员工的独特随机发布/招聘地点,所有员工已经在这些地方张贴,我正在尝试为他们生成一个新的随机发布地点,其中“where”条件是“员工新的随机位置将不等于其所在地,并且随机选择的员工,其名称必须小于或等于”地方表“中的”地方明确指定号码“
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
等等......
并且Places表格(具有员工数量的PlaceNames - 指定方式)是: -
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地名的Employees,
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;
另外我需要根据指定号码(在Places表格中)限制随机选择...即为每个员工随机分配一个PlaceName(来自Places),这不等于CurrentPosting和Home(在Employee中)和Place明智的指定不会超过给定的数字。
提前致谢。
答案 0 :(得分: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和home,而不是指定超过每列中指定的名称。但是,这可能会在多个地方返回同一名员工,因为他们可以根据该标准匹配多个员工。
修改强> 看到你的评论没有需要一个高性能的单一查询来解决这个问题(我甚至不确定是否可能),并且因为它似乎更像是一个“一次性”的过程,你将成为在调用时,我使用游标和一个临时表编写了以下代码来解决分配问题:
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
表进行实际更改。
答案 1 :(得分:1)
我假设约束是:
最重要的想法是要意识到你并不是在寻找“随机”的任务。你正在寻找一个位置的排列,这取决于每个人都移动到其他地方的条件。
我将描述管理者的答案。对于每种类型的员工,您可能需要三次查询。
关键思想是ManagerPositions表。这里有一个地方,一个序号和一个序号。以下是一个例子:
Araria 1 1
Araria 2 2
Arwal 1 3
Arungabad 1 4
查询通过使用row_number()函数连接到INFORMATION_SCHEMA.columns来创建此表以分配序列。这是一种在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)。第二个是行上的增量ID。
在每个经理的表格中找到当前位置。这应该是独一无二的,因为我考虑到了每个地方的经理人数。然后,向位置添加偏移量,并指定该位置。通过使偏移量大于maxseqnum,管理者可以保证移动到另一个位置(除非在一个位置有超过一半管理者的异常边界情况下)。
如果所有当前经理职位都已填补,那么这可以保证所有职位都移动到下一个位置。因为ManagerPositions使用随机id来分配seqnum,所以“next”位置是随机的,而不是id或字母顺序。
此解决方案确实让许多员工一起旅行到同一个新位置。您可以通过在表达式(m.seqnum+maxposseqnum+1)
中尝试“1”以外的值来稍微解决此问题。
我意识到有一种方法可以修改它,以防止当前位置和下一个位置之间的相关性。这样做如下:
我现在没有足够的时间为此编写SQL。