2016-03-18 14 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. 新しい列には、各ユーザーのゲームのランクを最大値で追加します。
  3. ランクは、ユーザーのゲームの中で最も高い金額のゲームのアルファベット順の位置です。ジャスの場合、彼の最高のゲームはyであり、それは彼のゲームの中で第2位に位置しています。
  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