2015-09-19 8 views
5

Sto cercando di utilizzare questa funzione SQL ricorsiva ma non riesco a farlo fare ciò che voglio, nemmeno vicino. Ho codificato la logica in un ciclo srotolato, chiedendo se può essere convertita in una singola query SQL ricorsiva, non lo stile di aggiornamento della tabella che ho usato.Convertitore di subquery Oracle Recursive convert

http://sqlfiddle.com/#!4/b7217/1

ci sono sei giocatori per essere ordinati. Hanno id, ID gruppo, punteggio e classifica.

Stato iniziale

+----+--------+-------+--------+ 
| id | grp_id | score | rank | 
+----+--------+-------+--------+ 
| 1 |  1 | 100 | (null) | 
| 2 |  1 | 90 | (null) | 
| 3 |  1 | 70 | (null) | 
| 4 |  2 | 95 | (null) | 
| 5 |  2 | 70 | (null) | 
| 6 |  2 | 60 | (null) | 
+----+--------+-------+--------+ 

voglio prendere la persona con il più alto punteggio iniziale e dare loro rango 1. Poi ho applicare 10 punti bonus per il punteggio di tutti coloro che hanno lo stesso ID gruppo. Prendi il livello più alto, assegna il grado 2, distribuisci punti bonus e così via fino a quando non ci sono giocatori rimasti.

L'ID utente rompe i legami.

I punti bonus cambiano la classifica. id = 4 inizialmente sembra essere in seconda posizione con 95, dietro il leader con 100 ma con il bonus di 10 punti, id = 2 si alza e prende il posto.

stato finale

+-----+---------+--------+------+ 
| ID | GRP_ID | SCORE | RANK | 
+-----+---------+--------+------+ 
| 1 |  1 | 100 | 1 | 
| 2 |  1 | 100 | 2 | 
| 4 |  2 | 95 | 3 | 
| 3 |  1 | 90 | 4 | 
| 5 |  2 | 80 | 5 | 
| 6 |  2 | 80 | 6 | 
+-----+---------+--------+------+ 

risposta

2

Questo è un bel po 'in ritardo, ma non sono sicuro che questo può essere fatto utilizzando ricorsiva CTE. Ho fatto però venuta in mente una soluzione che utilizza la clausola MODEL:

WITH SAMPLE (ID,GRP_ID,SCORE,RANK) AS (
SELECT 1,1,100,NULL FROM DUAL UNION 
SELECT 2,1,90,NULL FROM DUAL UNION 
SELECT 3,1,70,NULL FROM DUAL UNION 
SELECT 4,2,95,NULL FROM DUAL UNION 
SELECT 5,2,70,NULL FROM DUAL UNION 
SELECT 6,2,60,NULL FROM DUAL) 
SELECT ID,GRP_ID,SCORE,RANK FROM SAMPLE 
MODEL 
DIMENSION BY (ID,GRP_ID) 
MEASURES (SCORE,0 RANK,0 LAST_RANKED_GRP,0 ITEM_COUNT,0 HAS_RANK) 
RULES 
ITERATE (1000) UNTIL (ITERATION_NUMBER = ITEM_COUNT[1,1]) --ITERATE ONCE FOR EACH ITEM TO BE RANKED 
(
RANK[ANY,ANY] = CASE WHEN SCORE[CV(),CV()] = MAX(SCORE) OVER (PARTITION BY HAS_RANK) THEN RANK() OVER (ORDER BY SCORE DESC,ID) ELSE RANK[CV(),CV()] END, --IF THE CURRENT ITEM SCORE IS EQUAL TO THE MAX SCORE OF UNRANKED, ASSIGN A RANK 
LAST_RANKED_GRP[ANY,ANY] = FIRST_VALUE(GRP_ID) OVER (ORDER BY RANK DESC), 
SCORE[ANY,ANY] = CASE WHEN RANK[CV(),CV()] = 0 AND CV(GRP_ID) = LAST_RANKED_GRP[CV(),CV()] THEN SCORE[CV(),CV()]+10 ELSE SCORE[CV(),CV()] END, 
ITEM_COUNT[ANY,ANY] = COUNT(*) OVER(), 
HAS_RANK[ANY,ANY] = CASE WHEN RANK[CV(),CV()] <> 0 THEN 1 ELSE 0 END --TO SEPARATE RANKED/UNRANKED ITEMS 
) 
ORDER BY RANK; 

Non è molto bella, e ho il sospetto c'è un modo migliore per andare su questo, ma dà i risultati attesi.

Avvertenze:

che avrebbe dovuto aumentare il numero di iterazioni, se si dispone di più di quel numero di righe.

Questo esegue un re-ranking completo basato sul punteggio dopo ogni iterazione. Quindi, se abbiamo preso i tuoi dati campione, ma abbiamo cambiato il punteggio iniziale degli articoli da 2 a 95 anziché 90: dopo aver classificato l'articolo 1 e aver assegnato il bonus di 10 punti all'articolo 2, ora ha un punteggio di 105. Quindi lo classifichiamo come 1o e sposta l'articolo 1 in 2 °. Dovresti apportare alcune modifiche se questo non è il comportamento desiderato.