PHP/MySQL - 取得连胜

PHP/MySQL - Get Winning Streak

我正在尝试展示用户连胜记录,但我正在努力思考如何编写它 - 甚至是概念。

这是一个例子(从最新到最旧)db:

id | win_id| loss_id| player id
1  |  123  | 999    | 123
2  |  123  | 999    | 123
3  |  999  | 123    | 123
4  |  123  | 999    | 123

所以我想显示的是 player_id 的连胜记录:123 - 因此,它应该回显“2”来表示连胜记录,因为用户在 id 3 上输了时出现中断

当前连胜的可能解决方案:找到玩家获胜的所有比赛,但前提是之后没有失败:

SELECT COUNT(t.id)
  FROM table t
 WHERE t.player_id = 123
   AND t.win_id = 123 /* player 123 won */
   AND NOT EXISTS(SELECT * 
                    FROM table t2
                   WHERE t2.player_id = 123
                     AND t2.win_id <> 123 /* player 123 lost */
                 AND t2.id > t.id /* lost occur after the win we look at */
              )   

我理解你的问题是一个间隙和孤岛问题,你想将 "adjacent" 行组合在一起。

这是一种使用行号之间的差异来定义组的方法(这需要MySQL 8.0);然后,我们可以按连胜数进行汇总,按连胜长度降序排序,只保留上连胜数:

select win_id, count(*) no_wins, min(id) start_id, max(id) end_id
from (
    select 
        t.*,
        row_number() over(partition by player_id order by id) rn1,
        row_number() over(partition by player_id, win_id order by id) rn2
    from mytable t
    where player_id = 123
) t
where win_id = 123
group by win_id, rn1 - rn2
order by no_wins desc
limit 1

Demo on DB Fiddle:

| win_id | no_wins | start_id | end_id |
| ------ | ------- | -------- | ------ |
| 123    | 2       | 1        | 2      |

这将显示用户 123 的最高连胜记录 它适用于 mysql 5.x

我添加了一些数据来展示它的作用

CREATE TABLE wintable (
  `id` INTEGER,
  `win_id` INTEGER,
  `loss_id` INTEGER,
  `player id` INTEGER
);

INSERT INTO wintable
  (`id`, `win_id`, `loss_id`, `player id`)
VALUES
  ('1', '123', '999', '123'),
  ('2', '123', '999', '123'),
    ('3', '123', '777', '123'),
  ('4', '123', '777', '123'),
  ('5', '999', '123', '123'),
  ('6', '123', '999', '123'),
    ('7', '123', '999', '123'),
  ('8', '123', '999', '123'),
    ('9', '123', '777', '123'),
  ('10', '123', '777', '123'),
  ('11', '123', '999', '123'),
  ('12', '123', '999', '123'),
    ('13', '123', '777', '123'),
  ('14', '123', '777', '123'),
  ('15', '999', '123', '123');
✓

✓
SELECT 
    id,
    IF(`loss_id` <> 123,
        @num:=@num + 1,
        @num:=0) winstreek
FROM
    (SELECT 
        *
    FROM
        wintable
    WHERE
        `player id` = 123
    ORDER BY `id`) t1,
    (SELECT @num:=0) a
id | winstreek
-: | --------:
 1 |         1
 2 |         2
 3 |         3
 4 |         4
 5 |         0
 6 |         1
 7 |         2
 8 |         3
 9 |         4
10 |         5
11 |         6
12 |         7
13 |         8
14 |         9
15 |         0
SELECT MAX(winstreek) winstreek
FROM 
(SELECT 
    id,
    IF(`loss_id` <> 123,
        @num:=@num + 1,
        @num:=0) winstreek
FROM
    (SELECT 
        *
    FROM
        wintable
    WHERE
        `player id` = 123
    ORDER BY `id`) t1,
    (SELECT @num:=0) a) b;
| winstreek |
| --------: |
|         9 |

db<>fiddle here