2016-03-18 8 views
7

Dies bringt zurück, was ich will, aber gibt es einen einfacheren, eleganteren Ansatz?Hinzufügen eines Rangs zur ersten Zeile jeder Gruppe

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; 

Es gibt diese:

enter image description here

Hier ist die erste Tabelle:

enter image description here

Was das Skript tut, ist dies:

  1. Eine neue Spalte zur ursprünglichen Tabelle hinzufügen
  2. In neue Spalte fügen Sie den Rang des Spiels für jeden userAcc mit dem höchsten Betrag hinzu.
  3. Der Rang ist die alphabetische Position des Spiels mit der höchsten Anzahl unter den Spielen des Benutzers. Für jas ist sein höchstes Spiel y und das ist der zweite Platz unter seinen Spielen.
  4. Der Rang in Schritt 3 sollte nur gegen das erste alphabetische Spiel des jeweiligen Benutzers gehen.
+0

Sie sollten die Frage bearbeiten und die Ergebnisse als auch bieten. –

+0

@GordonLinoff .... wird jetzt tun – whytheq

Antwort

4

Sie benötigen hierfür keine join. Sie können Akkumulation verwenden.

Wenn ich das richtig verstanden:

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

Sehr elegante Antwort. – whytheq

Verwandte Themen