Tal vez algo como esto:
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)
Eso debería intentar hacer coincidir a los empleados al azar en función de su designación descartando la misma publicación actual y el hogar, y no asignar más de lo que se especifica en cada columna para la designación. Sin embargo, esto podría devolver al mismo empleado para varios lugares, ya que podrían coincidir con más de uno según ese criterio.
EDITAR: Después de ver su comentario acerca de no tener la necesidad de una consulta única de alto rendimiento para resolver este problema (que no estoy seguro de que sea posible), y dado que parece ser más un proceso "único" que será llamando, escribí el siguiente código usando un cursor y una tabla temporal para resolver su problema de asignaciones:
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
La idea básica es que itera sobre los empleados, en orden aleatorio, y asigna a cada uno un Lugar aleatorio que cumple con los criterios de diferentes domicilios y puestos actuales, además de controlar la cantidad que se asigna a cada lugar para cada Designación. para asegurarse de que las ubicaciones no estén "sobreasignadas" para cada rol.
Este fragmento no en realidad alterar sus datos sin embargo. El SELECT
final declaración simplemente devuelve las asignaciones propuestas. Sin embargo, puede modificarlo muy fácilmente para realizar cambios reales en su Employee
tabla en consecuencia.