I assume the limitations are:
- The employee cannot move to the same place in which he / she is located.
- All sites must have at least one employee in each category where the employee is expected.
The most important idea is to realize that you are not looking for a "random" task. You are looking for a rearrangement of positions, provided that everyone moves to another place.
I will describe the answer for managers. You will probably need three queries for each type of employee.
The main idea is the ManagerPositions table. This is a place, a sequential number and a serial number inside a place. The following is an example:
Araria 1 1 Araria 2 2 Arwal 1 3 Arungabad 1 4
The query creates this table by joining INFORMATION_SCHEMA.columns with the row_number () function to assign a sequence. This is a quick and dirty way to get the sequence in SQL Server - but it’s completely correct if the maximum number you need (that is, the maximum number of managers anywhere) is less than the number of columns in the database. There are other methods for handling a more general case.
The next key idea is to rotate places, not to randomly select them. This uses ideas from arithmetic modulo - add an offset and take the remainder for the total number of positions. The final request looks like this:
with ManagerPositions as ( select p.*, row_number() over (order by placerand, posseqnum) as seqnum, nums.posseqnum from (select p.*, newid() as placerand from places p ) p join (select row_number() over (order by (select NULL)) as posseqnum from INFORMATION_SCHEMA.COLUMNS c ) nums on p.Manager <= nums.posseqnum ), managers as ( select e.*, mp.seqnum from (select e.*, row_number() over (partition by currentposting order by newid() ) as posseqnum from Employees e where e.Designation = 'Manager' ) e join ManagerPositions mp on e.CurrentPosting = mp.PlaceName and e.posseqnum = mp.posseqnum ) select m.*, mp.PlaceId, mp.PlaceName from managers m cross join (select max(seqnum) as maxseqnum, max(posseqnum) as maxposseqnum from managerPositions mp ) const join managerPositions mp on (m.seqnum+maxposseqnum+1) % maxseqnum + 1 = mp.seqnum
Well, I understand that it is difficult. You have a table for each manager position (not an account, as in your application, the presence of a row for each position is important). There are two ways to determine a position. First in place and counting in place (posseqnum). The second is an incremental row identifier.
Find the current position in the table for each manager. This must be unique because I take into account the number of managers in each place. Then add the offset to the position and assign this place. Having an offset greater than maxseqnum, managers are guaranteed to move to another place (with the exception of unusual boundary cases when more than half of managers have one place).
If all positions of the current manager are filled, this ensures that everyone moves to the next place. Since a random identifier is used for scheduling to assign seqnum, the "next" place is random, not the next identifier or in alphabetical order.
In this decision, there are many employees traveling together in the same new place. You can fix this somewhat by trying values other than "1" in the expression (m.seqnum+maxposseqnum+1) .
I understand that there is a way to change this to prevent a correlation between the current location and the next location. This does the following:
- Randomly assigns seqnum ManagerPosition
- Compare the different offsets in the table, evaluating each by the number of times when the two positions in the table separated by this offset are the same.
- Choose an offset with a minimum rating (which is preferably 0).
- Use this bias in the final agreement.
I do not have enough time to write SQL for this.