2016-03-18 61 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. 在新列中,爲每個userAcc添加最高金額的遊戲排名。
  3. 排名是遊戲中用戶遊戲中數量最高的字母位置。所以對於jas而言,他的最高分是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