本文目录导读:

在PHP项目中统计“定位球得分占比”,核心是先定义清楚“定位球”的范围(通常指:角球、任意球(直接/间接)、点球、界外球或战术配合后的进球),然后再通过SQL查询或数组统计来计算。
以下我给你一套从SQL查询到PHP计算的完整解决方案,你可以直接套用。
第一步:定义数据表结构(假设)
假设你有一个 goals 表,结构如下(这是最常用的设计):
-- 进球记录表
CREATE TABLE goals (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT NOT NULL, -- 比赛ID
player_id INT, -- 进球球员ID
goal_type ENUM('open_play', 'corner', 'free_kick', 'penalty', 'own_goal') NOT NULL,
-- open_play = 运动战, corner = 角球, free_kick = 任意球, penalty = 点球, own_goal = 乌龙球
minute INT, -- 进球分钟
created_at TIMESTAMP
);
第二步:PHP后端核心代码
这里给你两个版本的统计逻辑,一个用原生的MySQLi,一个用PDO(推荐)。
使用原生 SQL 一次性查询(最高效)
<?php
// 假设你已经连接了数据库 $conn (MySQLi)
// 1. 统计所有非乌龙球的进球总数
$sqlTotal = "SELECT COUNT(*) AS total
FROM goals
WHERE goal_type != 'own_goal'"; // 通常乌龙球不计入进攻统计
$resultTotal = $conn->query($sqlTotal);
$totalGoals = $resultTotal->fetch_assoc()['total'];
// 2. 统计定位球进球数
// 定位球 = 角球 + 任意球 + 点球
$sqlSetPiece = "SELECT
SUM(CASE WHEN goal_type IN ('corner', 'free_kick', 'penalty') THEN 1 ELSE 0 END) AS set_piece_goals,
SUM(CASE WHEN goal_type = 'open_play' THEN 1 ELSE 0 END) AS open_play_goals,
SUM(CASE WHEN goal_type = 'corner' THEN 1 ELSE 0 END) AS corner_goals,
SUM(CASE WHEN goal_type = 'free_kick' THEN 1 ELSE 0 END) AS free_kick_goals,
SUM(CASE WHEN goal_type = 'penalty' THEN 1 ELSE 0 END) AS penalty_goals
FROM goals
WHERE goal_type != 'own_goal'";
$resultSetPiece = $conn->query($sqlSetPiece);
$data = $resultSetPiece->fetch_assoc();
// 3. 计算占比(防止除以零)
$setPieceGoals = $data['set_piece_goals'];
$percentage = ($totalGoals > 0) ? round(($setPieceGoals / $totalGoals) * 100, 2) : 0;
// 4. 输出结果
echo "总进球数: " . $totalGoals . "<br>";
echo "定位球进球数: " . $setPieceGoals . "<br>";
echo "定位球得分占比: " . $percentage . "% <br>";
echo "<hr>";
echo "<br>";
echo "角球占比: " . round(($data['corner_goals'] / max($totalGoals,1)) * 100, 2) . "%<br>";
echo "任意球占比: " . round(($data['free_kick_goals'] / max($totalGoals,1)) * 100, 2) . "%<br>";
echo "点球占比: " . round(($data['penalty_goals'] / max($totalGoals,1)) * 100, 2) . "%<br>";
$conn->close();
?>
PDO + 预处理(适合框架或更安全的项目)
<?php
// 假设 $pdo 是 PDO 连接实例
// 总进球数(排除乌龙)
$stmt = $pdo->query("SELECT COUNT(*) FROM goals WHERE goal_type != 'own_goal'");
$totalGoals = $stmt->fetchColumn();
// 定位球分类统计
$stmt = $pdo->query("
SELECT
COUNT(CASE WHEN goal_type IN ('corner', 'free_kick', 'penalty') THEN 1 END) AS set_piece,
COUNT(CASE WHEN goal_type = 'corner' THEN 1 END) AS corner,
COUNT(CASE WHEN goal_type = 'free_kick' THEN 1 END) AS free_kick,
COUNT(CASE WHEN goal_type = 'penalty' THEN 1 END) AS penalty
FROM goals
WHERE goal_type != 'own_goal'
");
$stats = $stmt->fetch(PDO::FETCH_ASSOC);
// 计算比例
$percentage = $totalGoals > 0 ? round(($stats['set_piece'] / $totalGoals) * 100, 1) : 0;
echo "定位球得分占比: {$percentage}%";
?>
第三步:如果你只统计【某一场特定比赛】或【某个赛季】
只需在上述SQL的 WHERE 子句后添加筛选条件:
-- 筛选某场比赛 WHERE match_id = 123 AND goal_type != 'own_goal' -- 筛选某个赛季(假设你有赛季关联) WHERE match_id IN (SELECT id FROM matches WHERE season_id = 2024) AND goal_type != 'own_goal'
第四步:如果是纯PHP数组(没有数据库)
如果你是从第三方API获取的数据,数据在PHP数组里,可以这样算:
$goals = [
['type' => 'open_play', 'player' => 'A'],
['type' => 'corner', 'player' => 'B'],
['type' => 'penalty', 'player' => 'C'],
['type' => 'free_kick', 'player' => 'D'],
// ...其他数据
];
$total = 0;
$setPiece = 0;
foreach ($goals as $goal) {
if ($goal['type'] == 'own_goal') continue; // 跳过乌龙球
$total++;
if (in_array($goal['type'], ['corner', 'free_kick', 'penalty'])) {
$setPiece++;
}
}
$percent = $total > 0 ? round($setPiece / $total * 100, 2) : 0;
echo "定位球占比: {$percent}%";
最后提醒你一下(关于业务逻辑)
常见的处理差异点:
- 乌龙球:通常不计入球队的定位球统计,但如果你想把乌龙球也算作“对方定位球得分”(通常不这么干),请自行调整上面的
WHERE条件。 - 点球:有些统计口径会把点球算作定位球,有些则不算(因为点球主要是个人技术对抗门将),默认上面的代码是算的,如果你不想算,把
penalty从IN子句里去掉即可。 - 任意球间接配合:如果进球前经过1次传球配合,但第一脚是任意球,通常依然算作定位球,这取决于你的
goal_type字段的录入规则。
如果想把这个统计做成一个函数或类(GoalStatistics::getSetPiecePercentage()),或者需要适配 Laravel / ThinkPHP 框架的代码写法,告诉我你用的框架,我可以再给你写框架版本。