PHP项目:统计冲刺跑次数谁更多?
这是一个常见的"数据统计+比较"需求,下面给你一个完整的实现思路和代码示例。

需求分析
假设场景:有一群运动员,每人可以多次记录"冲刺跑"成绩,需要统计谁的冲刺跑次数最多。
需要的数据结构:
- 运动员(用户)
- 每次冲刺跑记录(属于某个运动员)
数据库设计
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);
-- 冲刺跑记录表
CREATE TABLE sprint_records (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
distance DECIMAL(5,2) COMMENT '距离(米)',
duration DECIMAL(5,2) COMMENT '用时(秒)',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
核心统计代码(PHP + MySQL)
方法1:用 SQL 直接分组统计(推荐)
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '123456');
// 统计每人冲刺跑次数,按次数降序
$sql = "
SELECT u.id, u.name, COUNT(s.id) AS sprint_count
FROM users u
LEFT JOIN sprint_records s ON u.id = s.user_id
GROUP BY u.id, u.name
ORDER BY sprint_count DESC
";
$stmt = $pdo->query($sql);
$ranking = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 输出结果
echo "冲刺跑次数排行榜:\n";
foreach ($ranking as $index => $row) {
echo ($index + 1) . ". {$row['name']} —— {$row['sprint_count']} 次\n";
}
// 找出谁最多(可能并列)
$maxCount = $ranking[0]['sprint_count'] ?? 0;
$winners = array_filter($ranking, fn($r) => $r['sprint_count'] == $maxCount);
if (count($winners) === 1) {
$winner = reset($winners);
echo "\n🏆 冲刺跑次数最多的是:{$winner['name']},共 {$winner['sprint_count']} 次\n";
} else {
$names = implode('、', array_column($winners, 'name'));
echo "\n🏆 并列第一:{$names},各 {$maxCount} 次\n";
}
方法2:用 PHP 数组统计(数据量小时用)
<?php
// 假设从数据库取出的原始记录
$records = [
['user_id' => 1, 'name' => '张三'],
['user_id' => 2, 'name' => '李四'],
['user_id' => 1, 'name' => '张三'],
['user_id' => 3, 'name' => '王五'],
['user_id' => 1, 'name' => '张三'],
['user_id' => 2, 'name' => '李四'],
];
// 统计次数
$counts = [];
foreach ($records as $r) {
$uid = $r['user_id'];
if (!isset($counts[$uid])) {
$counts[$uid] = ['name' => $r['name'], 'count' => 0];
}
$counts[$uid]['count']++;
}
// 按次数降序
uasort($counts, fn($a, $b) => $b['count'] <=> $a['count']);
// 输出
foreach ($counts as $item) {
echo "{$item['name']}:{$item['count']} 次\n";
}
只想要"谁最多"
如果只关心第一名,SQL 更简洁:
$sql = "
SELECT u.name, COUNT(s.id) AS cnt
FROM users u
JOIN sprint_records s ON u.id = s.user_id
GROUP BY u.id, u.name
ORDER BY cnt DESC
LIMIT 1
";
$top = $pdo->query($sql)->fetch(PDO::FETCH_ASSOC);
echo "冲刺跑最多:{$top['name']}({$top['cnt']} 次)";
几个实际注意点
| 场景 | 建议 |
|---|---|
| 数据量大 | 给 sprint_records.user_id 加索引 |
| 需要按时间段统计 | SQL 加 WHERE s.created_at BETWEEN ? AND ? |
| 并列第一 | 用 LIMIT 1 会漏掉,改用上面的 array_filter 方案 |
| 排除0次用户 | 把 LEFT JOIN 改成 INNER JOIN |
| 性能优化 | 频繁统计可加缓存表或 Redis |
进阶:按时间段统计
$sql = "
SELECT u.name, COUNT(s.id) AS cnt
FROM users u
JOIN sprint_records s ON u.id = s.user_id
WHERE s.created_at >= :start AND s.created_at < :end
GROUP BY u.id, u.name
ORDER BY cnt DESC
";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':start' => '2024-01-01 00:00:00',
':end' => '2024-02-01 00:00:00',
]);
如果你能告诉我具体的业务场景(体育训练打卡?游戏排行榜?学校体测?)以及已有的表结构,我可以给你更贴合的实现代码。