Peut-être quelque chose comme ça :
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)
Cela devrait tenter de faire correspondre les employés au hasard en fonction de leur désignation en supprimant le même poste actuel et la même maison, et ne pas attribuer plus que ce qui est spécifié dans chaque colonne pour la désignation. Cependant, cela pourrait renvoyer le même employé pour plusieurs lieux, car ils pourraient correspondre à plus d'un en fonction de ce critère.
MODIF : Après avoir vu votre commentaire sur le fait de ne pas avoir besoin d'une requête unique très performante pour résoudre ce problème (ce dont je ne suis même pas sûr qu'il soit même possible), et puisqu'il semble s'agir davantage d'un processus "ponctuel" que vous serez appelant, j'ai écrit le code suivant à l'aide d'un curseur et d'une table temporaire pour résoudre votre problème d'affectation :
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
L'idée de base est qu'il parcourt les employés, dans un ordre aléatoire, et attribue à chacun un lieu aléatoire qui répond aux critères de différents domiciles et affectations actuelles, ainsi que le contrôle du montant attribué à chaque lieu pour chaque désignation. pour s'assurer que les emplacements ne sont pas "sur-affectés" pour chaque rôle.
Cet extrait n'est pas modifient en fait vos données. Le dernier SELECT
L'instruction renvoie simplement les affectations proposées. Cependant, vous pouvez très facilement le modifier pour apporter des modifications réelles à votre Employee
tableau en conséquence.