PHP 项目实现"人盯人防守成功率"统计
你需要明确一下需求,我先给你一个通用的实现方案和关键代码示例,因为"人盯人防守成功率"在篮球/足球统计中定义不同,我按篮球场景来写。

先明确业务定义
"人盯人防守成功率"通常指:
成功率 = 成功防守回合数 / 总盯人防守回合数 × 100%
什么算"成功"? 常见判定:
- 对手未得分
- 对手失误
- 对手投篮不中
- 造成进攻犯规
什么算"失败"?
- 对手得分
- 被突破导致失分
- 防守犯规送罚球
数据库设计
-- 球员表
CREATE TABLE players (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
team VARCHAR(50)
);
-- 防守回合记录表
CREATE TABLE defense_records (
id INT PRIMARY KEY AUTO_INCREMENT,
player_id INT, -- 防守人
opponent_id INT, -- 被防守人
match_id INT, -- 比赛ID
defense_type ENUM('man','zone') DEFAULT 'man', -- 防守类型
result ENUM('success','fail') NOT NULL, -- 结果
reason VARCHAR(50), -- 原因: steal/miss/score/foul...
quarter TINYINT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (player_id) REFERENCES players(id)
);
核心 PHP 代码
配置 & 数据库连接 db.php
<?php
$pdo = new PDO('mysql:host=localhost;dbname=basketball;charset=utf8mb4',
'root', 'password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
计算成功率的模型 DefenseStats.php
<?php
require 'db.php';
class DefenseStats
{
private PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
/**
* 统计某个球员的人盯人防守成功率
*/
public function manToManRate(int $playerId, ?int $matchId = null): array
{
$sql = "SELECT
COUNT(*) AS total,
SUM(result = 'success') AS success,
SUM(result = 'fail') AS fail
FROM defense_records
WHERE player_id = :pid
AND defense_type = 'man'";
$params = ['pid' => $playerId];
if ($matchId !== null) {
$sql .= " AND match_id = :mid";
$params['mid'] = $matchId;
}
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
$total = (int)$row['total'];
$success = (int)$row['success'];
$rate = $total > 0 ? round($success / $total * 100, 2) : 0.0;
return [
'player_id' => $playerId,
'total' => $total,
'success' => $success,
'fail' => (int)$row['fail'],
'rate' => $rate, // 百分比,例:73.21
];
}
/**
* 全队排行(按成功率降序)
*/
public function teamRanking(int $matchId): array
{
$sql = "SELECT p.id, p.name,
COUNT(*) AS total,
SUM(d.result='success') AS success,
ROUND(SUM(d.result='success') / COUNT(*) * 100, 2) AS rate
FROM defense_records d
JOIN players p ON p.id = d.player_id
WHERE d.defense_type = 'man' AND d.match_id = :mid
GROUP BY p.id, p.name
HAVING total >= 5
ORDER BY rate DESC";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['mid' => $matchId]);
return $stmt->fetchAll();
}
}
调用示例 index.php
<?php
require 'DefenseStats.php';
$stats = new DefenseStats($pdo);
// 单个球员本赛季人盯人成功率
$result = $stats->manToManRate(playerId: 7);
printf("球员%d:%d/%d,成功率 %.2f%%\n",
$result['player_id'],
$result['success'],
$result['total'],
$result['rate']
);
// 本场比赛全队排行
foreach ($stats->teamRanking(matchId: 101) as $r) {
printf("%-10s %3d/%3d %.2f%%\n",
$r['name'], $r['success'], $r['total'], $r['rate']);
}
输出示例:
球员7:11/15,成功率 73.33%
张三 11/15 73.33%
李四 9/12 75.00%
王五 4/10 40.00%
进阶:加入"加权成功率"
不同防守结果价值不同,可以加权:
// 权重:抢断 1.2,逼迫失误 1.1,投篮不中 1.0,得分 -1.0,犯规 -0.8
$weights = [
'steal' => 1.2,
'turnover' => 1.1,
'miss' => 1.0,
'score' => -1.0,
'foul' => -0.8,
];
$sql = "SELECT SUM(CASE reason
WHEN 'steal' THEN 1.2
WHEN 'turnover' THEN 1.1
WHEN 'miss' THEN 1.0
WHEN 'score' THEN -1.0
WHEN 'foul' THEN -0.8
END) AS score,
COUNT(*) AS total
FROM defense_records
WHERE player_id = ? AND defense_type='man'";
常见坑提醒
| 问题 | 说明 |
|---|---|
| 除零错误 | total=0 时必须返回 0,不能直接除 |
| 样本太小 | 出场<5次不建议排名(用 HAVING total >= 5) |
| 换防归属 | 挡拆换防后,谁算防守人?建议记录表存"实际防守人" |
| 时间维度 | 是"本场"还是"赛季"?一定要在 SQL 里区分 match_id |
| 快攻/协防 | 是否算人盯人?最好和录像剪辑规则对齐 |
你能补充下具体场景吗?
- 是篮球还是足球?
- 有没有现成的数据表结构?
- 是要网页展示(配图表)还是接口返回 JSON?
告诉我这些,我可以给你贴合你项目的完整代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播