php项目统计传球成功率哪队更高?

wen PHP项目 5

PHP项目:统计传球成功率哪队更高

下面给你一个完整的 PHP 实现方案,包含数据模型、统计逻辑和示例代码。

php项目统计传球成功率哪队更高?

数据表设计(MySQL)

-- 球队表
CREATE TABLE teams (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL
);
-- 比赛表
CREATE TABLE matches (
    id INT PRIMARY KEY AUTO_INCREMENT,
    home_team_id INT NOT NULL,
    away_team_id INT NOT NULL,
    match_date DATE
);
-- 传球记录表(核心)
CREATE TABLE passes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    match_id INT NOT NULL,
    team_id INT NOT NULL,
    player_id INT,
    is_success TINYINT(1) NOT NULL DEFAULT 0,  -- 1=成功 0=失败
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_match_team (match_id, team_id)
);

核心统计逻辑

传球成功率 = 成功传球数 ÷ 总传球数 × 100%

PHP 实现代码

数据库连接(PDO)

<?php
// db.php
$host = '127.0.0.1';
$db   = 'football';
$user = 'root';
$pass = '';
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

统计一场比赛中各队传球成功率

<?php
// stats_match.php
require 'db.php';
function getMatchPassStats(PDO $pdo, int $matchId): array
{
    $sql = "
        SELECT
            t.id                              AS team_id,
            t.name                            AS team_name,
            COUNT(p.id)                       AS total_passes,
            SUM(p.is_success)                 AS success_passes,
            ROUND(SUM(p.is_success) / COUNT(p.id) * 100, 2) AS success_rate
        FROM passes p
        JOIN teams t ON t.id = p.team_id
        WHERE p.match_id = :match_id
        GROUP BY t.id, t.name
        ORDER BY success_rate DESC
    ";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':match_id' => $matchId]);
    return $stmt->fetchAll();
}
// 使用示例
$matchId = 1;
$stats = getMatchPassStats($pdo, $matchId);
echo "比赛 #{$matchId} 传球成功率统计:\n";
foreach ($stats as $row) {
    printf(
        "%s:%d/%d = %.2f%%\n",
        $row['team_name'],
        $row['success_passes'],
        $row['total_passes'],
        $row['success_rate']
    );
}
// 判断哪队更高
if (count($stats) === 2) {
    $winner = $stats[0]['success_rate'] > $stats[1]['success_rate']
        ? $stats[0]['team_name']
        : ($stats[0]['success_rate'] < $stats[1]['success_rate']
            ? $stats[1]['team_name']
            : '两队持平');
    echo "\n传球成功率更高的是:{$winner}\n";
}

统计整个赛季 / 多场比赛的累计传球成功率

<?php
// stats_season.php
require 'db.php';
function getSeasonPassStats(PDO $pdo, ?string $startDate = null, ?string $endDate = null): array
{
    $where = [];
    $params = [];
    if ($startDate) {
        $where[] = 'm.match_date >= :start';
        $params[':start'] = $startDate;
    }
    if ($endDate) {
        $where[] = 'm.match_date <= :end';
        $params[':end'] = $endDate;
    }
    $whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
    $sql = "
        SELECT
            t.id                              AS team_id,
            t.name                            AS team_name,
            COUNT(p.id)                       AS total_passes,
            SUM(p.is_success)                 AS success_passes,
            ROUND(SUM(p.is_success) / COUNT(p.id) * 100, 2) AS success_rate
        FROM passes p
        JOIN teams t   ON t.id = p.team_id
        JOIN matches m ON m.id = p.match_id
        {$whereSql}
        GROUP BY t.id, t.name
        HAVING total_passes > 0
        ORDER BY success_rate DESC
    ";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    return $stmt->fetchAll();
}
// 示例:统计 2024 赛季
$stats = getSeasonPassStats($pdo, '2024-01-01', '2024-12-31');
echo "2024 赛季各队传球成功率排行:\n";
echo str_repeat('-', 50) . "\n";
printf("%-20s %8s %8s %8s\n", '球队', '总传球', '成功', '成功率');
echo str_repeat('-', 50) . "\n";
foreach ($stats as $row) {
    printf(
        "%-20s %8d %8d %7.2f%%\n",
        $row['team_name'],
        $row['total_passes'],
        $row['success_passes'],
        $row['success_rate']
    );
}
// 直接拿到第一名
if (!empty($stats)) {
    echo "\n>>> 传球成功率最高:{$stats[0]['team_name']} ({$stats[0]['success_rate']}%)\n";
}

对比两支指定球队(常用于"哪队更高")

<?php
// compare_two_teams.php
require 'db.php';
function compareTeamsPassRate(PDO $pdo, int $teamA, int $teamB): array
{
    $sql = "
        SELECT
            t.id, t.name,
            COUNT(p.id) AS total,
            SUM(p.is_success) AS success,
            ROUND(SUM(p.is_success)/COUNT(p.id)*100, 2) AS rate
        FROM passes p
        JOIN teams t ON t.id = p.team_id
        WHERE p.team_id IN (:a, :b)
        GROUP BY t.id, t.name
    ";
    $stmt = $pdo->prepare($sql);
    $stmt->bindValue(':a', $teamA, PDO::PARAM_INT);
    $stmt->bindValue(':b', $teamB, PDO::PARAM_INT);
    $stmt->execute();
    $rows = $stmt->fetchAll();
    $map = array_column($rows, null, 'team_id');
    $a = $map[$teamA] ?? ['name' => 'A', 'rate' => 0, 'total' => 0, 'success' => 0];
    $b = $map[$teamB] ?? ['name' => 'B', 'rate' => 0, 'total' => 0, 'success' => 0];
    $higher = $a['rate'] > $b['rate'] ? $a
        : ($b['rate'] > $a['rate'] ? $b : null);
    return ['team_a' => $a, 'team_b' => $b, 'higher' => $higher];
}
$result = compareTeamsPassRate($pdo, 1, 2);
echo "{$result['team_a']['name']}:{$result['team_a']['rate']}%\n";
echo "{$result['team_b']['name']}:{$result['team_b']['rate']}%\n";
echo $result['higher']
    ? "更高的是:{$result['higher']['name']}\n"
    : "两队持平\n";

关键要点

要点 说明
分母口径 一般只算"尝试传球",需排除传中、长传单独统计口径(可按需过滤 pass_type)
精度处理 用 ROUND(...,2),避免浮点误差展示;业务比较多用"成功数/总数"整数比较更稳
索引优化 passes(match_id, team_id) 和 passes(team_id, is_success) 组合索引
大数据量 可加 passes_daily 汇总表(预聚合),避免每次全表扫描
主客场区分 如需分主客场,JOIN matches 后按 home_team_id/away_team_id 拆分

如果你没有数据库,纯数组版

<?php
function calcPassRate(array $teams): array
{
    $result = [];
    foreach ($teams as $name => $p) {
        $total   = $p['success'] + $p['fail'];
        $rate    = $total > 0 ? round($p['success'] / $total * 100, 2) : 0;
        $result[$name] = compact('total', 'rate') + ['success' => $p['success']];
    }
    uasort($result, fn($a, $b) => $b['rate'] <=> $a['rate']);
    return $result;
}
$teams = [
    'A队' => ['success' => 320, 'fail' => 80],
    'B队' => ['success' => 410, 'fail' => 90],
];
$rank = calcPassRate($teams);
print_r($rank);
echo "更高:" . array_key_first($rank) . "\n";

如果你能告诉我:

  • 是否已有表结构(字段名不同)
  • 想统计单场、赛季还是两队对比
  • 是否需要区分主客场、传球类型(短传/长传/传中)

我可以帮你把代码改得更贴合你的项目。

抱歉,评论功能暂时关闭!