sql >> データベース >  >> RDS >> Sqlserver

職場をランダムに割り当て、各場所は指定された従業員の数を超えてはなりません

    多分このようなもの:

    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)
    

    これは、同じcurrentPostingとhomeを破棄する指定に基づいてランダムに従業員を照合することを試み、指定の各列で指定されている以上のものを割り当てないようにする必要があります。ただし、その基準に基づいて複数の場所に一致する可能性があるため、複数の場所で同じ従業員が返される可能性があります。

    編集: この問題を解決するために高性能の単一クエリを必要としないというコメントを見た後(それが可能かどうかはわかりませんが)、それは「1回限りの」プロセスのように思われるためです。呼び出して、割り当ての問題を解決するために、カーソルと1つの一時テーブルを使用して次のコードを作成しました。

    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
    

    基本的な考え方は、従業員をランダムな順序で繰り返し、さまざまな家と現在の投稿の基準を満たすランダムな場所を各従業員に割り当て、各指定の各場所に割り当てられる金額を制御することです。役割ごとに場所が「過剰に割り当てられていない」ことを確認します。

    このスニペットはありません ただし、実際にはデータを変更します。最後のSELECT ステートメントは、提案された割り当てを返すだけです。ただし、非常に簡単に変更して、Employeeに実際の変更を加えることができます。 それに応じてテーブル。



    1. plpgsql関数の動的ORDERBYおよびASC/DESC

    2. SQLクエリの結果が期待どおりに戻らないのはなぜですか?

    3. Webアプリケーションでの同時トランザクションを防止する

    4. Hibernateの問題:@OneToManyアノテーションが重複を返す