Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Phân công vị trí làm việc ngẫu nhiên và mỗi vị trí không được vượt quá số lượng nhân viên được chỉ định

Có thể như thế này:

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)

Điều đó sẽ cố gắng so khớp các nhân viên một cách ngẫu nhiên dựa trên chỉ định của họ, loại bỏ cùng hiện tại và nhà riêng, và không chỉ định nhiều hơn những gì được chỉ định trong mỗi cột cho chỉ định. Tuy nhiên, điều này có thể trả lại cùng một nhân viên cho một số nơi vì họ có thể khớp với nhiều nhân viên dựa trên tiêu chí đó.

CHỈNH SỬA: Sau khi xem nhận xét của bạn về việc không cần một truy vấn đơn lẻ có hiệu suất cao để giải quyết vấn đề này (điều mà tôi không chắc là có thể thực hiện được) và vì nó dường như là quá trình "một lần" mà bạn sẽ đang gọi, tôi đã viết mã sau bằng con trỏ và một bảng tạm thời để giải quyết vấn đề bài tập của bạn:

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

Ý tưởng cơ bản là nó lặp lại các nhân viên, theo thứ tự ngẫu nhiên và chỉ định cho mỗi người một Địa điểm ngẫu nhiên đáp ứng các tiêu chí về đăng bài tại nhà và hiện tại khác nhau, cũng như kiểm soát số tiền được chỉ định cho từng vị trí cho mỗi Chỉ định để đảm bảo rằng các vị trí không bị "chỉ định quá mức" cho từng vai trò.

Đoạn mã này không thực sự thay đổi dữ liệu của bạn. SELECT cuối cùng câu lệnh chỉ trả về các nhiệm vụ được đề xuất. Tuy nhiên, bạn rất có thể dễ dàng thay đổi nó để thực hiện các thay đổi thực sự đối với Employee của mình bảng tương ứng.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kiểm tra Thư chưa gửi trong SQL Server (T-SQL)

  2. LEN () trong SQL Server là gì?

  3. Làm cách nào để viết CẬP NHẬT SQL với bí danh Bảng trong SQL Server 2008?

  4. Phân tích cú pháp ngày giờ với thời gian bù đắp trong T-SQL

  5. Quản lý giao dịch đồng thời bằng cách sử dụng khóa trong SQL Server