2016-03-18 8 views
7

Questo sta restituendo quello che voglio ma c'è un approccio più semplice, più elegante?Aggiungere un rango alla prima riga di ogni gruppo

IF OBJECT_ID('TEMPDB..#test') IS NOT NULL DROP TABLE #test; 
CREATE TABLE #test 
(
    userAcc VARCHAR(100), 
    game VARCHAR(100), 
    amount INT 
); 

INSERT INTO #test 
values 
    ('jas', 'x', 10), 
    ('jas', 'y', 100), 
    ('jas', 'z', 20), 
    ('sam', 'j', 10), 
    ('sam', 'q', 5); 



--initial table sample 
SELECT userAcc, 
     game, 
     amount 
FROM #test; 


WITH 
X AS 
(
    SELECT rn = ROW_NUMBER() OVER (PARTITION BY userAcc ORDER BY game), 
      userAcc, 
      game, 
      amount, 
      rk = RANK() OVER (PARTITION BY userAcc ORDER BY amount DESC) 
    FROM #test 
), 
Y AS 
(
    SELECT RK,userAcc, 
      game, 
      targ = rn 
    FROM X 
    WHERE rk = 1 
) 
SELECT X.userAcc, 
     X.game, 
     X.amount, 
     ISNULL(Y.targ,0) 
FROM X 
     LEFT OUTER JOIN Y 
     ON 
     X.userAcc = Y.userAcc AND 
     X.rn = Y.rk 
ORDER BY X.userAcc,X.rn; 

Si restituisce questo:

enter image description here

Ecco la tabella iniziale:

enter image description here

Che lo script sta facendo è questo:

  1. Aggiungere una nuova colonna alla tabella originale
  2. Nella nuova colonna aggiungere il rango del gioco per ogni utenteAcc con l'importo più alto.
  3. Il rango è la posizione alfabetica del gioco con l'importo più alto tra i giochi dell'utente. Quindi per jas il suo gioco più alto è y e questo è posizionato al 2 ° posto tra i suoi giochi.
  4. Il rango trovato nel passaggio 3 deve andare solo contro il primo gioco alfabetico del rispettivo utente.
+0

è necessario modificare la domanda e fornire i risultati pure. –

+0

@GordonLinoff .... lo farà ora – whytheq

risposta

4

Per questo non è necessario un join. Puoi usare l'accumulo.

Se ho capito bene:

select userAcc, game, amount, 
     isnull((case when rn = 1 
       then max(case when rk = 1 then rn end) over (partition by userAcc) 
      end),0) as newcol 
    from (select t.*, 
       ROW_NUMBER() OVER (PARTITION BY userAcc ORDER BY game) as rn, 
       RANK() OVER (PARTITION BY userAcc ORDER BY amount DESC) as rk 
     from #test t 
     ) t 
    order by userAcc; 
+0

Risposta molto elegante. – whytheq