Sqlserver
 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, и да не присвоява повече от това, което е посочено във всяка колона за обозначението. Това обаче може да върне един и същ служител за няколко места, тъй като те биха могли да съответстват на повече от едно въз основа на тези критерии.

РЕДАКТИРАНЕ: След като видях коментара ви за липсата на нужда от високоефективна единична заявка за решаване на този проблем (което не съм сигурен, че дори е възможно), и тъй като изглежда, че е по-скоро „еднократен“ процес, вие ще бъдете обаждайки се, написах следния код, използвайки курсор и една временна таблица, за да разреша проблема ви с присвояванията:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Кодиране на кирилица в C#

  2. Добавете колони към съществуваща таблица в базата данни на SQL Server

  3. SQL Server:ИЗБЕРЕТЕ само редовете с MAX(DATE)

  4. DB Connection низ в Web.config за използване на прикачена .mdf база данни няма да работи

  5. Вмъкване на заявка в SQL функция