2013-01-14 64 views
1

我读过这些例子,但无法让它适用于我的示例。群组的MySQL限制记录

我有一个表'玩家'与列'PID'和'名称'和一张'卡'与列'PID','点'。

玩家记录有多张卡片记录。

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

此查询返回eveything我需要,但不限于每个名称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 
+0

您需要使用临时变量来进行排名。我建议你练习使用明确的'JOIN's。 – Kermit

回答

1

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

SELECT IF(@prev_name = p.name,@n:[email protected]+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子句将限制实际返回给客户端的行。

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 with Demo