2016-03-18 4 views
7

Это возвращает то, что я хочу, но есть ли более простой, более элегантный подход?Добавление ранга в первый ряд каждой группы

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; 

возвращает это:

enter image description here

Вот исходная таблица:

enter image description here

Что скрипт делает это:

  1. Добавить новый столбец в исходную таблицу
  2. В новой колонке добавьте ранг игры для каждого пользователяAcc с наибольшей суммой.
  3. Ранг - это алфавитная позиция игры с наибольшей суммой среди игр пользователя. Так что для его самой высокой игры является y, и это занимает второе место среди его игр.
  4. Ранг, найденный на шаге 3, должен идти только против первой алфавитной игры соответствующего пользователя.
+0

Вы должны отредактировать вопрос и предоставить результаты. –

+0

@GordonLinoff .... сделаю сейчас – whytheq

ответ

4

Для этого вам не нужен join. Вы можете использовать накопление.

Если я правильно понимаю:

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

Очень элегантный ответ. – whytheq

Смежные вопросы