PHP项目:统计扑救次数,看哪个门将更忙?
下面给你一个完整的思路 + 可运行的 PHP 示例代码,用来统计各门将的扑救次数,并判断"谁更忙"。

需求分析
"谁更忙"可以量化成几个指标:
| 指标 | 含义 |
|---|---|
| 扑救次数 | 直接反映工作量 |
| 出场次数 | 平均每场扑救更公平 |
| 场均扑救 | 排除出场差异 |
| 繁忙指数 | 综合权重(可自定义) |
数据库设计
-- 门将表
CREATE TABLE goalkeepers (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
team VARCHAR(50) NOT NULL
);
-- 比赛记录表(每场比赛每名门将一条)
CREATE TABLE saves (
id INT PRIMARY KEY AUTO_INCREMENT,
gk_id INT NOT NULL,
match_id INT NOT NULL,
save_count INT DEFAULT 0,
played TINYINT DEFAULT 1, -- 是否出场
match_date DATE,
FOREIGN KEY (gk_id) REFERENCES goalkeepers(id)
);
示例数据:
INSERT INTO goalkeepers (name, team) VALUES
('德赫亚', '曼联'), ('阿利松', '利物浦'), ('埃德森', '曼城');
INSERT INTO saves (gk_id, match_id, save_count, played, match_date) VALUES
(1, 1, 5, 1, '2024-01-01'), (1, 2, 7, 1, '2024-01-08'), (1, 3, 3, 1, '2024-01-15'),
(2, 1, 2, 1, '2024-01-01'), (2, 2, 4, 1, '2024-01-08'), (2, 3, 1, 1, '2024-01-15'),
(3, 1, 0, 1, '2024-01-01'), (3, 2, 1, 1, '2024-01-08'), (3, 3, 2, 1, '2024-01-15');
核心统计 SQL
SELECT
g.id,
g.name,
g.team,
COUNT(CASE WHEN s.played = 1 THEN 1 END) AS appearances,
COALESCE(SUM(s.save_count), 0) AS total_saves,
ROUND(
COALESCE(SUM(s.save_count), 0) /
NULLIF(COUNT(CASE WHEN s.played = 1 THEN 1 END), 0),
2
) AS avg_saves_per_match
FROM goalkeepers g
LEFT JOIN saves s ON s.gk_id = g.id
GROUP BY g.id, g.name, g.team
ORDER BY total_saves DESC;
PHP 完整实现(PDO 版)
<?php
// config.php
return [
'dsn' => 'mysql:host=127.0.0.1;dbname=football;charset=utf8mb4',
'user' => 'root',
'pass' => 'password',
];
<?php
// stats.php
$config = require 'config.php';
try {
$pdo = new PDO($config['dsn'], $config['user'], $config['pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
$sql = "
SELECT
g.id,
g.name,
g.team,
COUNT(CASE WHEN s.played = 1 THEN 1 END) AS appearances,
COALESCE(SUM(s.save_count), 0) AS total_saves,
ROUND(
COALESCE(SUM(s.save_count), 0) /
NULLIF(COUNT(CASE WHEN s.played = 1 THEN 1 END), 0),
2
) AS avg_saves
FROM goalkeepers g
LEFT JOIN saves s ON s.gk_id = g.id
GROUP BY g.id, g.name, g.team
ORDER BY total_saves DESC
";
$rows = $pdo->query($sql)->fetchAll();
// 繁忙指数计算(示例权重)
foreach ($rows as &$row) {
$row['busy_index'] = round(
$row['total_saves'] * 1.0 + $row['avg_saves'] * 0.5,
2
);
}
unset($row);
// 排序得到排名
usort($rows, fn($a, $b) => $b['busy_index'] <=> $a['busy_index']);
// 输出
echo "🏆 门将繁忙度排行榜\n";
echo str_repeat('=', 60) . "\n";
printf("%-4s %-10s %-10s %-6s %-6s %-8s %-8s\n",
'排名', '门将', '球队', '出场', '扑救', '场均扑救', '繁忙指数');
foreach ($rows as $i => $r) {
printf("%-4d %-10s %-10s %-6d %-6d %-8.2f %-8.2f\n",
$i + 1, $r['name'], $r['team'],
$r['appearances'], $r['total_saves'],
$r['avg_saves'], $r['busy_index']);
}
echo str_repeat('=', 60) . "\n";
echo "🔥 最忙门将:{$rows[0]['name']}({$rows[0]['team']})\n";
运行结果示例
🏆 门将繁忙度排行榜
============================================================
排名 门将 球队 出场 扑救 场均扑救 繁忙指数
1 德赫亚 曼联 3 15 5.00 17.50
2 阿利松 利物浦 3 7 2.33 8.17
3 埃德森 曼城 3 3 1.00 3.50
============================================================
🔥 最忙门将:德赫亚(曼联)
进阶建议
- 按时间段筛选:加
WHERE match_date BETWEEN ? AND ? - 对手强度加权:面对强队扑救加成
- 零封奖励:
save_count=0且球队获胜,说明门将轻松 - 可视化:用 Chart.js 输出柱状图
- 缓存:结果放入 Redis,避免每次全表扫描
- 粒度细化:区分"扑救类型"(点球、单刀、常规)
要不要我帮你扩展成 按赛季 / 按联赛分别统计 的版本,或者加上 前端图表展示?