Kanske något sånt här:
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)
Det bör försöka matcha anställda slumpmässigt baserat på deras beteckning som kasserar samma aktuella Posting och hem, och inte tilldela mer än vad som anges i varje kolumn för beteckningen. Detta kan dock returnera samma anställd för flera platser, eftersom de kan matcha mer än en baserat på det kriteriet.
EDIT: Efter att ha sett din kommentar om att du inte har ett behov av en högpresterande enskild fråga för att lösa detta problem (vilket jag inte är säker på är ens möjligt), och eftersom det verkar vara mer av en "engångsprocess" som du kommer att bli när jag ringde skrev jag upp följande kod med hjälp av en markör och en tillfällig tabell för att lösa ditt problem med tilldelningar:
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
Grundidén är att den itererar över de anställda, i slumpmässig ordning, och tilldelar var och en en slumpmässig plats som uppfyller kriterierna för olika hem och nuvarande utstationering, samt kontrollerar mängden som tilldelas varje plats för varje beteckning för att säkerställa att platserna inte är "övertilldelade" för varje roll.
Det här utdraget gör det inte faktiskt ändra din data dock. Den sista SELECT
uttalandet returnerar bara de föreslagna uppdragen. Men du kan mycket enkelt ändra den för att göra faktiska ändringar av din Employee
tabell därefter.