Może coś takiego:
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)
Powinno to próbować losowo dopasować pracowników na podstawie ich oznaczenia, odrzucając to samo bieżące publikowanie i dom, i nie przypisywać więcej niż to, co określono w każdej kolumnie dla oznaczenia. Może to jednak zwrócić tego samego pracownika na kilka miejsc, ponieważ mogą oni dopasować więcej niż jedno na podstawie tych kryteriów.
EDYTUJ: Po obejrzeniu twojego komentarza na temat braku potrzeby pojedynczego zapytania o wysokiej wydajności, aby rozwiązać ten problem (co nie jestem pewien, czy jest nawet możliwe), a ponieważ wydaje się to być bardziej „jednorazowym” procesem, będziesz dzwoniąc, napisałem następujący kod za pomocą kursora i jednej tabeli tymczasowej, aby rozwiązać twój problem z przypisaniami:
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
Podstawową ideą jest to, że iteruje po pracownikach w losowej kolejności i przypisuje każdemu losowe miejsce, które spełnia kryteria innego miejsca zamieszkania i bieżącego delegowania, a także kontroluje kwotę, która jest przypisana do każdego miejsca dla każdego Wyznaczenia aby upewnić się, że lokalizacje nie są „nadmiernie przypisane” do każdej roli.
Ten fragment nie faktycznie zmienić swoje dane. Ostatni SELECT
instrukcja po prostu zwraca proponowane przypisania. Jednak możesz bardzo łatwo go zmienić, aby wprowadzić rzeczywiste zmiany w swoim Employee
tabeli odpowiednio.