Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Tetapkan lokasi kerja secara acak dan setiap lokasi tidak boleh melebihi jumlah karyawan yang ditunjuk

Mungkin seperti ini:

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)

Itu harus mencoba untuk mencocokkan karyawan secara acak berdasarkan penunjukan mereka membuang saat iniPosting dan rumah yang sama, dan tidak menetapkan lebih dari apa yang ditentukan di setiap kolom untuk penunjukan. Namun, ini dapat mengembalikan karyawan yang sama untuk beberapa tempat, karena mereka dapat mencocokkan lebih dari satu berdasarkan kriteria tersebut.

EDIT: Setelah melihat komentar Anda tentang tidak perlunya kueri tunggal berkinerja tinggi untuk menyelesaikan masalah ini (yang saya tidak yakin bahkan mungkin), dan karena ini tampaknya lebih merupakan proses "satu kali" yang akan Anda lakukan menelepon, saya menulis kode berikut menggunakan kursor dan satu tabel sementara untuk menyelesaikan masalah tugas Anda:

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

Ide dasarnya adalah, bahwa ia mengulangi karyawan, dalam urutan acak, dan memberikan masing-masing Tempat acak yang memenuhi kriteria rumah yang berbeda dan posting saat ini, serta mengendalikan jumlah yang ditugaskan ke setiap tempat untuk setiap Penunjukan untuk memastikan bahwa lokasi tidak "ditugaskan secara berlebihan" untuk setiap peran.

Cuplikan ini tidak sebenarnya mengubah data Anda. SELECT final terakhir pernyataan hanya mengembalikan tugas yang diusulkan. Namun Anda dapat dengan mudah mengubahnya untuk membuat perubahan aktual pada Employee Anda tabel yang sesuai.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mencadangkan Database SQL Server menggunakan T-SQL

  2. Kolom teks tidak menyimpan lebih dari 8000 karakter

  3. Kolom IDENTITAS SQLServer dengan teks

  4. Membalikkan perubahan dari log transaksi di SQL Server 2008 R2?

  5. Cara Memigrasi Database SQL Server ke Database Azure SQL