PHP项目:统计冲刺跑次数谁更多
下面给你一个完整的实现思路和代码示例。

需求理解
假设你有一个记录跑步数据的数据表,run_records,字段包括:
iduser_id(用户)run_type(跑步类型,如 'sprint' 冲刺跑 / 'jog' 慢跑)distance(距离)created_at
目标:统计每个用户冲刺跑的次数,并按次数降序排列,找出谁最多。
数据库表结构示例
CREATE TABLE run_records (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
run_type VARCHAR(20) NOT NULL COMMENT 'sprint=冲刺跑, jog=慢跑',
distance DECIMAL(6,2) DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
核心 SQL 统计
SELECT
u.id,
u.name,
COUNT(r.id) AS sprint_count
FROM users u
LEFT JOIN run_records r
ON r.user_id = u.id
AND r.run_type = 'sprint'
GROUP BY u.id, u.name
ORDER BY sprint_count DESC;
说明:用
LEFT JOIN保证没跑过冲刺的用户也显示(次数为 0);如果只想看有冲刺记录的人,用INNER JOIN。
PHP 实现(PDO)
<?php
// db.php 连接配置
$host = '127.0.0.1';
$db = 'fitness';
$user = 'root';
$pass = '';
$dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";
try {
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $e) {
die('数据库连接失败: ' . $e->getMessage());
}
// 统计冲刺跑次数
$sql = "
SELECT
u.id,
u.name,
COUNT(r.id) AS sprint_count
FROM users u
LEFT JOIN run_records r
ON r.user_id = u.id
AND r.run_type = 'sprint'
GROUP BY u.id, u.name
ORDER BY sprint_count DESC, u.name ASC
";
$stmt = $pdo->query($sql);
$ranking = $stmt->fetchAll();
// 找出第一名(可能并列)
$topCount = $ranking[0]['sprint_count'] ?? 0;
$winners = array_filter($ranking, fn($row) => $row['sprint_count'] == $topCount);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">冲刺跑次数排行榜</title>
<style>
table { border-collapse: collapse; width: 400px; }
th, td { border: 1px solid #ccc; padding: 8px 12px; text-align: center; }
th { background: #f5f5f5; }
.top { background: #fff8d6; font-weight: bold; }
</style>
</head>
<body>
<h2>冲刺跑次数排行榜</h2>
<table>
<thead>
<tr><th>排名</th><th>用户</th><th>冲刺次数</th></tr>
</thead>
<tbody>
<?php $rank = 1; foreach ($ranking as $row): ?>
<tr class="<?= $row['sprint_count'] == $topCount && $topCount > 0 ? 'top' : '' ?>">
<td><?= $rank++ ?></td>
<td><?= htmlspecialchars($row['name']) ?></td>
<td><?= (int)$row['sprint_count'] ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p>
<strong>冲刺跑次数最多的用户:</strong>
<?php
if ($topCount == 0) {
echo '暂无冲刺记录';
} else {
echo implode('、', array_column($winners, 'name'))
. ",共 {$topCount} 次冲刺跑";
}
?>
</p>
</body>
</html>
进一步优化建议
-
按时间段统计(如本周/本月):
... AND r.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
-
按距离阈值判定冲刺(如果没有
run_type,可根据配速或距离判断):COUNT(CASE WHEN r.distance >= 0.1 AND r.distance <= 0.5 THEN 1 END) AS sprint_count
-
大数据量时给
(user_id, run_type)加联合索引:CREATE INDEX idx_user_type ON run_records(user_id, run_type);
-
输出 JSON 接口(给前端调用):
header('Content-Type: application/json'); echo json_encode([ 'ranking' => $ranking, 'top_count' => $topCount, 'winners' => array_values($winners), ], JSON_UNESCAPED_UNICODE);
如果你没有 run_type 字段
如果你的原始数据只有配速(pace,秒/公里)或时间距离,可以按业务规则定义"冲刺":配速快于 4 分/公里:
SELECT u.name, COUNT(r.id) AS sprint_count
FROM users u
LEFT JOIN run_records r
ON r.user_id = u.id AND r.pace <= 240 -- 4分钟=240秒/公里
GROUP BY u.id, u.name
ORDER BY sprint_count DESC;
需要我根据你的真实表结构(字段名、类型判定规则)改成可直接运行的代码吗?把你现有的表结构或相关代码贴出来,我可以帮你精确适配。