Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Przydziel losowo miejsce pracy, a każda lokalizacja nie powinna przekraczać liczby wyznaczonych pracowników

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jaki jest odpowiednik bigint w C#?

  2. Generuj wszystkie kombinacje w SQL

  3. Zapytanie o datę utworzenia tabeli SQL Server

  4. Jak dodać nową kolumnę tożsamości do tabeli w SQL Server?

  5. Dlaczego Asp.net MVC4 nie może używać bez plików cookie przechowywania stanu sesji SQL Server?