Получить рейтинг пользователя на основе суммы с нумерацией страниц - PullRequest
3 голосов
/ 24 января 2012

Есть несколько рейтинговых постов, но мне еще предстоит увидеть один, в котором рассматриваются, когда результаты разбиты на страницы и когда критерии ранжирования (в данном случае: баллы) равны предыдущему пользователю. Я попробовал несколько из ранее существующих примеров, но ни один не работал.

У меня есть таблица «users» со столбцом «id». У меня также есть таблица «points» со столбцами «user_id» и «amount».

Мне нужно:

1.) Пользователи с одинаковой суммой баллов имеют одинаковый ранг

Таблица очков

user_id     amount
   1          10
   2          20
   1           5
   3          20
   3          -5
   4          5

Ранг должен быть

rank     user_id    total
 1          2        20
 2          1        15
 2          3        15
 3          4        5

2.) Требуется поддерживать ранжирование с одной страницы на другую, чтобы в запросе собирался ранг, а не полученный PHP.

3.) Отображать ВСЕХ пользователей, а не только пользователей со строками в таблице баллов, потому что у некоторых пользователей есть 0 баллов, и я хочу, чтобы они отображались последними.

Сейчас я просто перечисляю пользователей в порядке их баллов, но их рейтинг не набирается, потому что он не работает.

$getfanspoints = mysql_query("SELECT DISTINCT id,
(SELECT SUM(amount) AS points FROM points WHERE points.user_id = users.id) AS points
FROM users
ORDER BY points DESC LIMIT $offset, $fans_limit", $conn);

Я прочитал эти решения, и ни одно из них не сработало.

[Блог Роланда] [1]

[Как получить ранг на основе суммы сумм] [2]

[MySQL, получить рейтинг пользователей] [3]

[Как получить рейтинг с помощью запроса MySQL] [4]

и несколько других, чью ссылку я сейчас не могу найти.

Есть предложения?

[EDIT]

Я использовал нижний ответ ypercube.

1 Ответ

1 голос
/ 24 января 2012
SELECT COUNT(*) AS rank
     , t.user_id
     , t.total 
FROM
      ( SELECT   user_id
             ,   SUM(amount) AS total
        FROM     points 
        GROUP BY user_id
      ) AS t
  JOIN
      ( SELECT DISTINCT
                 SUM(amount) AS total
        FROM     points 
        GROUP BY user_id
      ) AS dt
    ON 
        t.total <= dt.total
GROUP BY t.user_id
ORDER BY rank
       , user_id

Но вышеупомянутое может быть очень медленным с большим столом и часто присуждаемыми баллами. Может быть, действительно лучше иметь это и вычислять ранги в коде приложения:

SELECT   users.id    AS user_id
     ,   SUM(amount) AS total
FROM     
         users
  LEFT JOIN
         points
    ON   points.user_id = users.id
GROUP BY users.id
ORDER BY total DESC
       , user_id

Это также будет работать (отредактировано, чтобы работать с таблицей users и с OFFSET):

SELECT *
FROM
  ( SELECT
          @rank := @rank + (@t <> total) AS rank
        , user_id 
        , @t := total AS total
    FROM 
        ( SELECT   users.id AS user_id
               ,   COALESCE(SUM(amount),0) AS total
          FROM users
            LEFT JOIN points
              ON users.id = points.user_id
          GROUP BY users.id
        ) AS o
      CROSS JOIN
        ( SELECT @rank := 0, @t := -999999
        ) AS dummy
    ORDER BY total DESC
           , user_id
  ) tmp
LIMIT x OFFSET y
...