1

我已阅读示例,但无法使其适用于我的示例。

我有一个表'玩家',列'pid'和'name',还有一个表'card',列'pid','points'。

一个玩家记录有多个卡记录。

如何查询每个玩家的前 5 条记录?

此查询返回我需要的一切,但不限于每个名称 5 条记录。

SELECT p.pid, p.name, c.points as lp
FROM player as p, card as c
WHERE p.pid=c.pid
ORDER BY p.name,  lp DESC
4

2 回答 2

2

您可以使用变量为每个用户分配排名:

select pid, name, lp
from
(
    SELECT pid, 
        name, 
        points as lp,
        @prev := @curr,
        @curr := name,
        @rank := IF(@prev = @curr, @rank+1, 1) AS rank
    FROM
    (
      select p.pid, name, points
      FROM player as p
      INNER JOIN card as c
          ON p.pid=c.pid
    ) src, (SELECT @curr := null, @prev := null, @rank := 1) r
    ORDER BY name, points desc
) src
where rank <= 5
order by name, lp DESC;

请参阅带有演示的 SQL Fiddle

于 2013-01-14T22:14:04.830 回答
1

MySQL 不支持返回指定结果集所需的“分析”类型函数。我们可以通过使用 MySQL 的“用户变量”来模拟该功能。

SELECT IF(@prev_name = p.name,@n:=@n+1,@n:=1) AS seq
     , @prev_name := p.name AS name
     , c.points as lp
  FROM player as p
  JOIN card as c
    ON c.pid = p.pid
  JOIN (SELECT @n := 0, @prev_name := NULL) i
 HAVING seq <= 5
 ORDER BY p.name, lp DESC

请注意,此语句的结果集与您的原始语句不同,因为它返回一个额外的列“seq”。此列将返回 1、2、3 等值。指示这是否是特定 p.name 的“第一”、“第二”、“第三”等行。

用于推导它的表达式基本上是检查当前行上 p.name 的值是否与前一行中的值匹配。如果匹配,我们加 1;如果不匹配,则我们重置为零。

查询实际上会为每个 p.name 的所有行生成一个结果集;该HAVING子句将限制实际返回给客户端的行。

于 2013-01-14T22:27:15.157 回答