本文目录导读:

你这个问题缺少具体的 PHP 项目代码或数据表结构,我无法直接算出“进攻三区传球成功率”,不过我可以在假设常见结构的前提下,给你一套可直接套用的 PHP 计算逻辑,你把它接到自己的项目里即可。
先明确指标定义
进攻三区传球成功率通常定义为:
进攻三区传球成功率 = 进攻三区成功传球次数 ÷ 进攻三区传球总次数 × 100%
进攻三区”一般指:对方球门方向前场 1/3 区域(足球数据里常按 x 坐标 ≥ 球场长度 2/3 判定)。
假设你的数据表结构
常见有两种存法:
方案 A:传球事件表(推荐)
CREATE TABLE pass_events ( id INT PRIMARY KEY, match_id INT, player_id INT, team_id INT, start_x DECIMAL(5,2), -- 传球起点 x(0~100 或 0~105) start_y DECIMAL(5,2), end_x DECIMAL(5,2), -- 传球终点 x end_y DECIMAL(5,2), is_success TINYINT, -- 1 成功 0 失败 pitch_length DECIMAL(5,2) DEFAULT 105 );
方案 B:统计汇总表
CREATE TABLE team_zone_stats ( id INT PRIMARY KEY, match_id INT, team_id INT, zone VARCHAR(20), -- 'defensive','middle','attacking' passes_total INT, passes_success INT );
下面按方案 A给完整 PHP 示例(方案 B 更简单,最后附一句)。
PHP 计算代码(方案 A)
<?php
// db.php 里应有 $pdo(PDO 连接)
function attackingThirdPassSuccessRate(PDO $pdo, int $teamId, ?int $matchId = null): array
{
// 进攻三区判定:起点 x >= 2/3 场长
$sql = "
SELECT
COUNT(*) AS total_passes,
SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) AS success_passes
FROM pass_events
WHERE team_id = :team_id
AND start_x >= pitch_length * 2 / 3
";
$params = [':team_id' => $teamId];
if ($matchId !== null) {
$sql .= " AND match_id = :match_id";
$params[':match_id'] = $matchId;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$total = (int)($row['total_passes'] ?? 0);
$success = (int)($row['success_passes'] ?? 0);
$rate = $total > 0 ? round($success / $total * 100, 2) : 0.0;
return [
'team_id' => $teamId,
'match_id' => $matchId,
'total_passes' => $total,
'success_passes' => $success,
'success_rate' => $rate, // 百分比,如 78.35
];
}
// 用法示例
// $pdo = new PDO('mysql:host=localhost;dbname=football;charset=utf8mb4', 'user', 'pass');
// print_r(attackingThirdPassSuccessRate($pdo, 12)); // 某队全部比赛
// print_r(attackingThirdPassSuccessRate($pdo, 12, 1001)); // 某队某场比赛
输出示例:
Array
(
[team_id] => 12
[match_id] =>
[total_passes] => 210
[success_passes] => 168
[success_rate] => 80.0
)
如果你的表是方案 B(汇总表)
function attackingThirdRateFromStats(PDO $pdo, int $teamId, ?int $matchId = null): float
{
$sql = "SELECT SUM(passes_total) t, SUM(passes_success) s
FROM team_zone_stats
WHERE team_id = :team_id AND zone = 'attacking'";
$params = [':team_id' => $teamId];
if ($matchId !== null) {
$sql .= " AND match_id = :match_id";
$params[':match_id'] = $matchId;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$t = (int)$row['t']; $s = (int)$row['s'];
return $t > 0 ? round($s / $t * 100, 2) : 0.0;
}
几个容易踩的坑
- 坐标系要统一:
start_x是 0~100 还是 0~105?进攻方向是否统一(有的项目主客队方向相反,需要先翻转 x),如果主客队方向相反,SQL 里要按team_id判断是否用pitch_length - start_x。 - “进攻三区”按起点还是终点算:多数传球统计按起点所在区域归类;若要按“传入进攻三区”则用
end_x。 - 成功定义:
is_success=1是否已排除“传球出界/被断/门将扑救”等,需和你的数据字典对齐。 - 分母为 0 要返回 0 而不是报错(上面已处理)。
- 性能:
team_id + match_id + start_x建联合索引;数据量大时可在汇总表预计算。
如果你把实际的表名、字段名(或一段建表 SQL / 示例数据)贴出来,我可以直接改成贴合你项目的查询语句和 PHP 函数。