Сложный SQL-запрос - PullRequest
       11

Сложный SQL-запрос

5 голосов
/ 09 октября 2009

Действительно сложный оператор 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

Было бы очень приятно,если бы вы могли помочь мне =) Спасибо!

Ответы [ 4 ]

13 голосов
/ 09 октября 2009

Обновление:

Как отмечал @Steve Kass, я не заметил, что вы хотели только первые три игры.

Вот обновленная версия:

In SQL Server, Oracle и PostgreSQL 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
1 голос
/ 10 октября 2009

Я не думаю, что Кассной заметил, что вы просили топ-пользователей только для трех лучших игр (на основе общего количества сыгранных времен) . Вот запрос для этого (не тестировался на реальных данных, так как операторы CREATE TABLE и INSERT не были предоставлены). Я также включаю галстуки, которых Кассной не сделал, просто чтобы показать вам этот вариант.

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 голосов
/ 10 июля 2013
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 голосов
/ 03 ноября 2011
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...