sql >> Database teknologi >  >> RDS >> Sqlserver

Tildel tilfældigt arbejdssted, og hver placering bør ikke overstige antallet af udpegede medarbejdere

Måske noget som dette:

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 forsøge at matche medarbejdere tilfældigt baseret på deres betegnelse, der kasserer samme aktuelle Posting og hjem, og ikke tildele mere end det, der er angivet i hver kolonne for betegnelsen. Dette kan dog returnere den samme medarbejder flere steder, da de kan matche mere end én ud fra det kriterium.

EDIT: Efter at have set din kommentar om ikke at have et behov for en højtydende enkelt forespørgsel for at løse dette problem (hvilket jeg ikke er sikker på overhovedet er muligt), og da det ser ud til at være mere en "engangs"-proces, vil du blive opkald, skrev jeg følgende kode ved hjælp af en markør og en midlertidig tabel for at løse dit problem med opgaver:

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

Den grundlæggende idé er, at den itererer over medarbejderne, i tilfældig rækkefølge, og tildeler hver enkelt et tilfældigt sted, der opfylder kriterierne for forskellige hjem og aktuelle udstationeringer, samt kontrollerer det beløb, der bliver tildelt hvert sted for hver betegnelse for at sikre, at lokationerne ikke er "overtildelt" for hver rolle.

Dette uddrag ikke faktisk ændre dine data dog. Den endelige SELECT erklæring returnerer bare de foreslåede opgaver. Du kan dog meget nemt ændre den for at foretage faktiske ændringer af din Employee tabel i overensstemmelse hermed.



  1. MacOSX:autostart mysql ved opstart

  2. Fra tidsstemplet i SQL, valg af poster fra i dag, i går, denne uge, denne måned og mellem to datoer php mysql

  3. Når jeg først har aktiveret modeller i django, hvorfor kan jeg så ikke forespørge dem direkte i postgresql pgAdmin UI?

  4. 3 måder at få en liste over databaser i SQL Server (T-SQL)