как отслеживать набор очков в mysql - PullRequest
2 голосов
/ 10 июля 2020

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

У меня есть 2 таблицы

таблица навыков

+----+---------+---------------------+
| id |  name   |     created_at      |
+----+---------+---------------------+
|  1 | skill 1 | 2020-06-05 00:00:00 |
|  2 | skill 2 | 2020-06-05 00:00:00 |
|  3 | skill 3 | 2020-06-05 00:00:00 |
+----+---------+---------------------+

таблица оценок

+----+-----------+----------+-------+---------------------+
| id | player_id | skill_id | score |     created_at      |
+----+-----------+----------+-------+---------------------+
|  1 |         1 |        1 |     5 | 2020-06-06 00:00:00 |
|  2 |         1 |        1 |    10 | 2020-07-06 00:00:00 |
|  3 |         1 |        2 |     1 | 2020-07-06 00:00:00 |
|  4 |         2 |        1 |    11 | 2020-07-06 00:00:00 |
|  5 |         1 |        1 |    13 | 2020-07-07 00:00:00 |
|  6 |         1 |        2 |    10 | 2020-07-07 00:00:00 |
|  7 |         2 |        1 |    12 | 2020-07-07 00:00:00 |
|  8 |         1 |        1 |    20 | 2020-07-08 00:00:00 |
|  9 |         1 |        2 |    15 | 2020-07-08 00:00:00 |
| 10 |         2 |        1 |    17 | 2020-07-08 00:00:00 |
+----+-----------+----------+-------+---------------------+

мои ожидаемые результаты: -

24-часовой запрос

+-----------+---------+-------+------+
| player_id |  name   | score | gain |
+-----------+---------+-------+------+
|         1 | skill 1 |    20 |    7 |
|         1 | skill 2 |    15 |    5 |
+-----------+---------+-------+------+

7-дневный запрос

+-----------+---------+-------+------+
| player_id |  name   | score | gain |
+-----------+---------+-------+------+
|         1 | skill 1 |    20 |   10 |
|         1 | skill 2 |    15 |   14 |
+-----------+---------+-------+------+

31-дневный запрос

+-----------+---------+-------+------+
| player_id |  name   | score | gain |
+-----------+---------+-------+------+
|         1 | skill 1 |    20 |   15 |
|         1 | skill 2 |    15 |   14 |
+-----------+---------+-------+------+

пока что у меня есть следующее, но все это возвращает последние 2 записи для каждого навыка, я изо всех сил пытаюсь вычислить прирост и разные временные рамки

SELECT player_id, skill_id, name, score 
FROM (SELECT player_id, skill_id, name, score, 
      @skill_count := IF(@current_skill = skill_id, @skill_count + 1, 1) AS skill_count,
      @current_skill := skill_id 
      FROM skill_scores 
      INNER JOIN skills 
        ON skill_id = skills.id 
      WHERE player_id = 1
      ORDER BY skill_id, score DESC
     ) counted 
WHERE skill_count <= 2

Мне нужна помощь в выяснении запроса, который мне нужно создать для получения желаемых результатов, или лучше всего сделать это с помощью php вместо db?

EDIT: -

MYSQL 8.0.20 идентификаторы фиктивных данных - это автоматическое приращение primary_key, но для простоты я не указывал это: -

CREATE TABLE skills
   (
      id bigint,
      name VARCHAR(80)
   );
   
   CREATE TABLE skill_scores
   (
      id bigint,
      player_id bigint,
      skill_id bigint, 
      score bigint,
      created_at timestamp
   );
 
   INSERT INTO skills VALUES (1, 'skill 1'); 
   INSERT INTO skills VALUES (2, 'skill 2'); 
   INSERT INTO skills VALUES (3, 'skill 3'); 
 
   INSERT INTO skill_scores VALUES (1, 1, 1 , 5, '2020-06-06 00:00:00');
   INSERT INTO skill_scores VALUES (2, 1, 1 , 10, '2020-07-06 00:00:00');
   INSERT INTO skill_scores VALUES (3, 1, 2 , 1, '2020-07-06 00:00:00');
   INSERT INTO skill_scores VALUES (4, 2, 1 , 11, '2020-07-06 00:00:00');
   INSERT INTO skill_scores VALUES (5, 1, 1 , 13, '2020-07-07 00:00:00');
   INSERT INTO skill_scores VALUES (6, 1, 2 , 10, '2020-07-07 00:00:00');
   INSERT INTO skill_scores VALUES (7, 2, 1 , 12, '2020-07-07 00:00:00');
   INSERT INTO skill_scores VALUES (8, 1, 1 , 20, '2020-07-08 00:00:00');
   INSERT INTO skill_scores VALUES (9, 1, 2 , 15, '2020-07-08 00:00:00');
   INSERT INTO skill_scores VALUES (10, 2, 1 , 17, '2020-07-08 00:00:00');

Ответы [ 2 ]

1 голос
/ 10 июля 2020
WITH cte AS (
SELECT id, player_id, skill_id,
       FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) score, 
       FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) - FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at ASC) gain,
       ROW_NUMBER() OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) rn
FROM skill_scores
WHERE created_at BETWEEN @current_date - INTERVAL @interval DAY AND @current_date
)
SELECT cte.player_id, skills.name, cte.score, cte.gain
FROM cte
JOIN skills ON skills.id = cte.skill_id
WHERE rn = 1
ORDER BY player_id, name;

скрипка

Пс. Не понимаю, откуда берется gain=15 для 31-дневного периода - разница между '2020-07-08 00:00:00' и '2020-06-06 00:00:00' составляет 32 дней.

0 голосов
/ 10 июля 2020

Думаю, для этого вам понадобится (временная) таблица. Я назову это "player_skill_gains". В основном это навыки игроков, упорядоченные по created_at и с идентификатором auto_incremented:

CREATE TABLE player_skill_gains
(`id` int PRIMARY KEY AUTO_INCREMENT NOT NULL
                                          , `player_id` int
                                         , skill_id int
                                         , score int
                                         , created_at date)
;

INSERT INTO player_skill_gains(player_id, skill_id, score, created_at)
SELECT player_skills.player_id AS player_id
  , player_skills.skill_id
  , SUM(player_skills.score) AS score
, player_skills.created_at
FROM player_skills
GROUP BY player_skills.id, player_skills.skill_id, player_skills.created_at
ORDER BY player_skills.player_id, player_skills.skill_id, player_skills.created_at ASC;

Используя эту таблицу, мы можем относительно легко выбрать последнее умение для каждой строки (id-1). Используя это, мы можем рассчитать выигрыш:

SELECT player_skill_gains.player_id, skills.name, player_skill_gains.score
  , player_skill_gains.score - IFNULL(bef.score,0) AS gain
  , player_skill_gains.created_at
FROM player_skill_gains
  INNER JOIN skills ON player_skill_gains.skill_id = skills.id
  LEFT JOIN player_skill_gains AS bef ON (player_skill_gains.id - 1) = bef.id
      AND player_skill_gains.player_id = bef.player_id
      AND player_skill_gains.skill_id = bef.skill_id

Для различных запросов, которые вы хотите иметь (24 часа, 7 дней и т. Д. c.), Вам просто нужно указать необходимую часть where для запрос.

Вы можете увидеть все это в действии здесь: http://sqlfiddle.com/#! 9 / 1571a8 / 11/0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...