2009-10-09 91 views
5

真的很棘手的SQL语句,我在这里。尝试构建这个查询大约一小时。 也许你可以帮助我。棘手的SQL查询

我们有一张3列的表格: gamename |用户| times_played

查询应该选择排名前三的游戏(取决于总times_played)以及在该游戏中玩过最多次数的前三名用户=> 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 Server?甲骨文? Postgres的? – Asaph 2009-10-09 17:01:55

+0

哪种技术? MySQL的? SQL Server?你可以使用存储过程吗? – 2009-10-09 17:01:56

+0

@foriamstu更好的问题:*你应该使用存储过程吗?根据我的经验,几乎总是:'不'。当时似乎很方便,回来咬你维修。 – 2009-10-10 03:39:45

回答

13

更新:

由于@Steve Kass指出,我没有注意到你只是想在前三场比赛。

下面是更新后的版本:

SQL ServerOraclePostgreSQL 8.4

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 

MySQL

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

当你回答它时,它似乎很容易:-) – 2009-10-09 17:00:33

+0

我想它是“PARTITION BY” – 2009-10-09 17:01:19

+0

我会在Game中发出命令并确保结果以正确的顺序显示。 – 2009-10-09 17:02:15

1

我不认为Quassnoi注意到,您仅向前三名游戏请求顶级用户(根据总次数显示)。这是一个查询(没有在真实数据上测试,因为没有给出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'upvotes和没有做出,但一个simgle的话:) :) – Quassnoi 2009-10-10 19:23:54

+0

也许你发布是很少有错,人们认为这是浪费时间仔细观察。 :) – 2009-10-11 01:04:10

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

检查这一个 – 2013-07-10 09:09:39