Io parto dal presupposto i vincoli sono:
- Un dipendente non può andare nella stessa posizione s/he è attualmente a.
- Tutti i siti devono avere almeno un dipendente in ogni categoria, in cui è previsto un dipendente.
L'idea più importante è rendersi conto che non si sta cercando un compito "casuale". Stai cercando una permutazione delle posizioni, a condizione che tutti si spostino altrove.
Ho intenzione di descrivere una risposta per i gestori. Probabilmente vorrai tre query per ogni tipo di dipendente.
L'idea chiave è una tabella ManagerPositions. Questo ha un posto, un numero sequenziale e un numero sequenziale all'interno del luogo. Quanto segue è un esempio:
Araria 1 1
Araria 2 2
Arwal 1 3
Arungabad 1 4
La query crea questa tabella unendo ad INFORMATION_SCHEMA.COLUMNS con una funzione row_number() per assegnare una sequenza. Questo è un modo rapido e sporco per ottenere una sequenza in SQL Server, ma perfettamente valido fino a quando il numero massimo necessario (ovvero il numero massimo di gestori in una posizione) è inferiore al numero di colonne nel Banca dati. Esistono altri metodi per gestire il caso più generale.
L'idea chiave successiva è di ruotare i luoghi, piuttosto che sceglierli a caso. Questo utilizza idee dall'aritmetica modulo: aggiungi un offset e prendi il resto sul numero totale di posizioni. La query finale assomiglia a questa:
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
Ok, mi rendo conto che questo è complicato. Hai una tabella per ogni posizione manager (non un conteggio come nella tua dichiarazione, avere una riga per ogni posizione è importante). Ci sono due modi per identificare una posizione. Il primo è per luogo e per conteggio all'interno del luogo (posseqnum). Il secondo è un ID incrementale sulle righe.
Trova la posizione corrente nella tabella per ogni gestore. Questo dovrebbe essere unico, perché sto prendendo in considerazione il numero di manager in ogni luogo. Quindi, aggiungi un offset alla posizione e assegna quel posto. Avendo l'offset maggiore del massimo, i gestori sono garantiti per spostarsi in un'altra posizione (tranne in casi limite insoliti in cui una posizione ha più della metà dei gestori).
Se tutte le posizioni attuali del gestore sono occupate, questo garantisce che tutti si spostino nella posizione successiva. Poiché ManagerPositions utilizza un ID casuale per assegnare il seqnum, il "prossimo" posto è casuale, non successivo per id o alfabeticamente.
Questa soluzione ha molti dipendenti che viaggiano insieme nella stessa nuova posizione. È possibile risolvere questo problema cercando valori diversi da "1" nell'espressione (m.seqnum+maxposseqnum+1)
.
Mi rendo conto che esiste un modo per modificarlo, per evitare la correlazione tra il luogo corrente e il luogo successivo. Questo fa la seguente:
- Assegna la seqnum di ManagerPosition casualmente
- Compare diversi offset nella tabella, valutare ogni per il numero di volte due posizioni nella tabella, separati da tale correttore, sono gli stessi.
- Scegliere l'offset con la valutazione minima (che è preferibilmente 0).
- Utilizzare tale offset nella clausola di corrispondenza finale.
Non ho abbastanza tempo per scrivere l'SQL per questo.
Grazie per l'aiuto di @Pablo ... come ottenere senza lo stesso dipendente per più posti ... quali criteri aggiuntivi che possiamo mettere - per favore suggerisci ad esempio di ottenere questo senza ripetere lo stesso Emp per Luoghi diversi. – Gaurav
Sto ricevendo una ripetizione indesiderata di mp.PlaceName, ad esempio nella tabella Places "Arizona 1", ovvero Arizona ha bisogno di un solo manager ma questa query restituisce più di 1 manager ad Arozona e la stessa situazione con la maggior parte dei luoghi .. – Gaurav
Ho appena ricevuto testato con il set di dati aggiornato che hai postato sopra, e sembra ancora funzionare bene. Non assegnando mai più di quanto specificato in Places. Sei sicuro che la ripetizione che hai visto non riguardasse un ruolo diverso, come l'OP o l'Impiegato? Inoltre, poiché i confronti qui sono fatti usando le stringhe in Designation, assicurati che tutte le voci di "Manager" siano scritte nello stesso modo, senza spazi, ecc. –