2009-10-09 10 views
5

本当にトリッキーなSQL文私はここにいます。このクエリを約1時間作成しようとしています。 多分あなたは私を助けることができます。トリッキーなSQLクエリ

3列の表があります。 gamename |ユーザー| times_played

クエリでは、上位3つのゲーム(合計times_playedに依存)とこのゲームで最も多く再生した上位3人のユーザー=> 9行を選択する必要があります。あなたが私を助けることができれば

The result is like: 
CounterStrike | Smith 
CounterStrike | Jonny 
Counterstrike | Hans 
WoW   | George 
WoW   | Bob 
Wow   | Frank 
Need For Speed| James 
Need For Speed| Marion 
Need For Speed| Scarlet 

は=、非常にいいだろう) ありがとう!

+0

? MySQL? SQLサーバー?オラクル? Postgres? – Asaph

+0

どの技術ですか? MySQL? SQLサーバー?ストアドプロシージャを使用できますか? –

+0

@foriamstuより良い質問:*あなた*ストアドプロシージャを使用する必要がありますか?私の経験では、ほとんど常に:「いいえ」。当時は便利だったようですが、メンテナンスの際にあなたを噛ませるように戻ってきます。 –

答えて

13

更新:@Steve Kassが指摘したように

、私はあなただけの最初の3つのゲームを望んでいたことに気づきませんでした。 SQL Server

OraclePostgreSQL 8.4

MySQL
SELECT gamename, user 
FROM (
     SELECT r.gamename, user, 
       ROW_NUMBER() OVER (PARTITION BY game ORDER BY times_played DESC) rn, 
     FROM (
       SELECT gamename, ROW_NUMBER() OVER (ORDER BY SUM(times_played) DESC) AS game_rn 
       FROM results 
       GROUP BY 
         gamename 
       ) g 
     JOIN results r 
     ON  r.gamename = g.gamename 
     WHERE game_rn <= 3 
     ) q 
WHERE rn <= 3 
ORDER BY 
     gamename, times_played DESC 

SELECT ro.gamename, ro.user 
FROM (
     SELECT gamename, SUM(times_played) AS rank 
     FROM results 
     ORDER BY 
       rank DESC 
     LIMIT 3 
     ) rd 
JOIN results ro 
ON  ro.gamename >= rd.gamename 
     AND ro.gamename <= rd.gamename 
     AND 
     (ro.times_played, ro.id) <= 
     (
     SELECT ri.times_played, ri.id 
     FROM results ri 
     WHERE ri.gamename = rd.gamename 
     ORDER BY 
       ri.times_played DESC, ri.id DESC 
     LIMIT 2, 1 
     ) 
ORDER BY 
     gamename, times_played DESC 

あなたはそれを想定して、仕事にこのクエリのPRIMARY KEYが必要になります。ここ

は、更新されたバージョンですidと呼ばれます。

これは私のブログにこの記事で詳しく説明されている:以下

PostgreSQL 8.3

と:

SELECT gamename, ((ri)[s]).user 
FROM (
     SELECT gamename, ri, generate_series(1, 3) AS s 
     FROM (
       SELECT ro.gamename, 
         ARRAY 
         (
         SELECT ri 
         FROM results ri 
         WHERE ri.gamename = ro.gamename 
         ORDER BY 
           times_played DESC 
         LIMIT 3 
         ) AS ri 
       FROM (
         SELECT gamename, SUM(times_played) AS rank 
         FROM results 
         ORDER BY 
           rank DESC 
         LIMIT 3 
         ) rd 
       ) q 
     ) q2 
ORDER BY 
     gamename, s 
+3

それはあなたがそれに答えるときにとても簡単に思えるでしょう:-) –

+0

"PARTITION BY"だと思います。 –

+0

Gameとrnの順番で投げて結果が正しい順序で表示されるようにします。 –

1

私はQuassnoiがあることに気づいたとは思いませんあなたは上位3人のゲームのトップユーザー(合計times_playedに基づいて)を依頼しました。ここでは、CREATE TABLE文とINSERT文が指定されていないため、実際のデータではテストされていません。私はQuassnoiがしなかったネクタイも含めて、あなたにそのオプションを示すだけです。

with GamesPlays(gamename,totalPlays) as (
    select 
    gamename, sum(times_played) 
    from results 
    group by gamename 
), GamesRanked(gamename,gameRank) as (
    select 
    gamename, 
    rank() over (
     order by totalPlays desc 
    ) 
    from GamesPlays 
), ResultsRanked(gamename,user,userRank) as (
    select 
    gamename, 
    user, 
    rank() over (
     partition by user 
     order by times_played desc 
    ) 
    from results; 
) 
    select 
    G.gamename, R.user 
    from ResultsRanked as R 
    join GamesRanked as G 
    on G.gamename = R.gamename 
    where gameRank <= 3 
    and userRank <= 3 
    order by 
    gameRank,userRank; 
+0

それを指摘してくれてありがとう。 '12'のアップノートがありますが、誰も作ったものではありませんが、シームレスな発言です。 – Quassnoi

+0

あなたが投稿するものが間違っていることはめったにありません。 :) –

0
DROP TABLE #game_stats 


CREATE TABLE #game_stats (gamename VARCHAR(50),users VARCHAR(50),times_played INT); 

INSERT INTO #game_stats VALUES ('Counter Strike','Kamesh',2); 
INSERT INTO #game_stats VALUES ('Counter Strike','Hely',4); 
INSERT INTO #game_stats VALUES ('Counter Strike','Maitri',1); 
INSERT INTO #game_stats VALUES ('Counter Strike','Laxmi',5); 
INSERT INTO #game_stats VALUES ('WOW','Kamesh',21); 
INSERT INTO #game_stats VALUES ('WOW','laxmi',60); 
INSERT INTO #game_stats VALUES ('WOW','Hely',7); 
INSERT INTO #game_stats VALUES ('NFS','Hely',5); 
INSERT INTO #game_stats VALUES ('NFS','Kamesh',1); 
INSERT INTO #game_stats VALUES ('NFS','Maitri',12); 
INSERT INTO #game_stats VALUES ('NFS','Laxmi',21); 
INSERT INTO #game_stats VALUES ('CODE ZERO','Kamesh',45); 
INSERT INTO #game_stats VALUES ('CODE ZERO','Maitri',52); 
INSERT INTO #game_stats VALUES ('CODE ZERO','Laxmi',21); 
INSERT INTO #game_stats VALUES ('CODE ZERO','Kamesh',41); 
INSERT INTO #game_stats VALUES ('HITMAN','Maitri',142); 
INSERT INTO #game_stats VALUES ('HITMAN','Laxmi',210); 
INSERT INTO #game_stats VALUES ('HITMAN','Kamesh',41); 
INSERT INTO #game_stats VALUES ('HITMAN','Maitri',102); 
INSERT INTO #game_stats VALUES ('HITMAN','Mani',142); 
INSERT INTO #game_stats VALUES ('NFS','Mani',210); 
INSERT INTO #game_stats VALUES ('CODE ZERO','Mani',41); 
INSERT INTO #game_stats VALUES ('WOW','Mani',102); 

select * from #game_stats; 

SELECT RN, 
Gamename, 
Users, 
Times_played 
FROM 
(
    SELECT ROW_NUMBER() OVER (PARTITION BY GS.gamename ORDER BY SUM(GS.times_played) DESC) AS RN, 
     GS.gamename, 
     GS.users, 
     SUM(gs.times_played) as times_played 

FROM #game_stats GS 
WHERE GS.gamename IN (
      SELECT TOP 3 gamename 
          FROM #game_stats 
          GROUP BY gamename 
                   ORDER BY sum(times_played) DESC 
        ) 
GROUP BY GS.gamename,GS.users 
) a 
WHERE RN<=3 
ORDER BY gamename,times_played DESC 
0
SELECT DISTINCT GN,US,GT,UT 
FROM 
(SELECT GN,US,GT,UT, 
     Dense_rank() over(ORDER BY GT DESC) RGT, 
     Dense_rank() over(partition BY GN ORDER BY UT DESC) RUT 
FROM 
    (SELECT gamename GN, 
      users US, 
      times_played TP, 
      sum(times_played) over (partition BY gamename) GT , 
      sum(times_played) over (partition BY gamename,users) UT 
    FROM game_stats)) 
WHERE RGT <4 
AND RUT < 4 
ORDER BY GT DESC, 
     UT DESC 
何データベース
+0

これで確認する –

関連する問題