sql >> Databáze >  >> RDS >> Sqlserver

Náhodně přidělujte pracovní místo a každé místo by nemělo překročit počet určených zaměstnanců

Možná něco takového:

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)

To by se mělo pokusit přiřadit zaměstnance náhodně na základě jejich označení a vyřadit stejné aktuální zasílání a domov, a nikoli přiřadit více, než je uvedeno v každém sloupci pro označení. To by však mohlo vrátit stejného zaměstnance na několik míst, protože by se na základě tohoto kritéria mohli shodovat s více než jedním.

UPRAVIT: Poté, co jste viděli váš komentář o tom, že k vyřešení tohoto problému nepotřebujete vysoce výkonný jediný dotaz (což si nejsem jistý, zda je vůbec možné), a protože se zdá, že jde spíše o „jednorázový“ proces, budete Při volání jsem napsal následující kód pomocí kurzoru a jedné dočasné tabulky, abych vyřešil váš problém s přiřazením:

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

Základní myšlenkou je, že iteruje zaměstnance v náhodném pořadí a každému z nich přiřadí náhodné místo, které splňuje kritéria různého domova a aktuálního vysílání, a také kontroluje množství, které bude každému místu přiděleno pro každé označení. abyste zajistili, že umístění nebudou "přeřazena" pro každou roli.

Tento úryvek není ve skutečnosti však změnit svá data. Poslední SELECT příkaz pouze vrátí navrhovaná přiřazení. Můžete jej však velmi snadno upravit tak, aby prováděl skutečné změny vašeho Employee podle toho.



  1. Výkon vkládání MySQL InnoDB (Windows)

  2. Uložená procedura MySQL vs funkce, kterou bych kdy použil?

  3. Zaručuje UNION ALL pořadí výsledné sady

  4. Získejte polygonové body mysql