PHP项目:两队边路突破能力对比分析
下面给你一个完整的实现思路和代码示例,用于对比两支球队的边路突破能力。

指标设计
边路突破能力可从以下维度衡量:
| 指标 | 含义 | 数据来源 |
|---|---|---|
| 边路突破次数 | 左右两侧成功过人次数 | 比赛事件数据 |
| 突破成功率 | 成功突破/尝试突破 | 事件统计 |
| 传中次数 | 边路传中 | 事件统计 |
| 传中成功率 | 成功传中/总传中 | 事件统计 |
| 边路进攻占比 | 边路进攻/总进攻 | 区域数据 |
| 边路射门/助攻 | 边路创造的射门机会 | 事件数据 |
| 边路球员速度/盘带 | 球员属性 | 球员数据 |
数据库表设计
-- 球队表
CREATE TABLE teams (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
-- 比赛表
CREATE TABLE matches (
id INT PRIMARY KEY AUTO_INCREMENT,
home_team_id INT,
away_team_id INT,
match_date DATE
);
-- 边路突破事件表(核心)
CREATE TABLE wing_breakthroughs (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT,
team_id INT,
player_id INT,
side ENUM('left','right') NOT NULL, -- 左右边路
is_success TINYINT DEFAULT 0, -- 是否成功
breakthrough_type ENUM('dribble','cross','one_two') DEFAULT 'dribble',
minute INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 传中事件表
CREATE TABLE crosses (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT,
team_id INT,
player_id INT,
side ENUM('left','right'),
is_success TINYINT DEFAULT 0,
minute INT
);
核心计算逻辑(PHP)
<?php
class WingAnalysis
{
private PDO $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
/**
* 获取某球队的边路突破统计
* @param int $teamId
* @param int $lastN 最近N场(0表示全部)
*/
public function getTeamWingStats(int $teamId, int $lastN = 0): array
{
// 1. 突破数据
$sql = "SELECT
side,
COUNT(*) AS attempts,
SUM(is_success) AS successes,
ROUND(SUM(is_success) / COUNT(*) * 100, 1) AS success_rate
FROM wing_breakthroughs
WHERE team_id = :team_id";
$params = [':team_id' => $teamId];
// 限制最近N场
if ($lastN > 0) {
$sql .= " AND match_id IN (
SELECT id FROM matches
WHERE (home_team_id = :t1 OR away_team_id = :t2)
ORDER BY match_date DESC LIMIT :n
)";
$params[':t1'] = $teamId;
$params[':t2'] = $teamId;
$params[':n'] = $lastN;
}
$sql .= " GROUP BY side";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$breakthroughs = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 2. 传中数据
$sql2 = "SELECT
side,
COUNT(*) AS attempts,
SUM(is_success) AS successes,
ROUND(SUM(is_success) / COUNT(*) * 100, 1) AS success_rate
FROM crosses
WHERE team_id = :team_id";
$stmt = $this->db->prepare($sql2 . " GROUP BY side");
$stmt->execute([':team_id' => $teamId]);
$crosses = $stmt->fetchAll(PDO::FETCH_ASSOC);
return [
'team_id' => $teamId,
'breakthrough' => $this->formatSideData($breakthroughs),
'cross' => $this->formatSideData($crosses),
];
}
/**
* 整理左右边路数据
*/
private function formatSideData(array $rows): array
{
$result = [
'left' => ['attempts' => 0, 'successes' => 0, 'success_rate' => 0],
'right' => ['attempts' => 0, 'successes' => 0, 'success_rate' => 0],
];
foreach ($rows as $row) {
$side = $row['side'];
$result[$side] = [
'attempts' => (int)$row['attempts'],
'successes' => (int)$row['successes'],
'success_rate' => (float)$row['success_rate'],
];
}
// 计算总突破数
$result['total'] = $result['left']['successes'] + $result['right']['successes'];
return $result;
}
/**
* 两队对比
*/
public function compare(int $teamA, int $teamB, int $lastN = 0): array
{
$dataA = $this->getTeamWingStats($teamA, $lastN);
$dataB = $this->getTeamWingStats($teamB, $lastN);
// 计算综合边路评分
$scoreA = $this->calcWingScore($dataA);
$scoreB = $this->calcWingScore($dataB);
return [
'team_a' => $dataA,
'team_b' => $dataB,
'score' => [
'team_a' => $scoreA,
'team_b' => $scoreB,
'winner' => $scoreA > $scoreB ? 'A' : ($scoreB > $scoreA ? 'B' : 'draw'),
],
];
}
/**
* 综合评分(可自行调权重)
*/
private function calcWingScore(array $data): float
{
$b = $data['breakthrough'];
$c = $data['cross'];
// 权重:突破成功 40% / 突破成功率 20% / 传中成功 20% / 传中成功率 20%
$breakthroughScore = $b['left']['successes'] + $b['right']['successes'];
$breakthroughRate = $this->avgRate([
$b['left']['success_rate'],
$b['right']['success_rate'],
]);
$crossScore = $c['left']['successes'] + $c['right']['successes'];
$crossRate = $this->avgRate([
$c['left']['success_rate'],
$c['right']['success_rate'],
]);
return round(
$breakthroughScore * 0.4 +
$breakthroughRate * 0.2 +
$crossScore * 0.2 +
$crossRate * 0.2,
2
);
}
private function avgRate(array $rates): float
{
$rates = array_filter($rates, fn($v) => $v > 0);
return $rates ? array_sum($rates) / count($rates) : 0;
}
}
调用示例
$db = new PDO('mysql:host=localhost;dbname=football', 'root', '');
$analysis = new WingAnalysis($db);
$result = $analysis->compare($teamA = 1, $teamB = 2, $lastN = 5);
// 输出:双队左右边路对比
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
返回结果示例
{
"team_a": {
"team_id": 1,
"breakthrough": {
"left": {"attempts": 45, "successes": 28, "success_rate": 62.2},
"right": {"attempts": 30, "successes": 15, "success_rate": 50.0},
"total": 43
},
"cross": {
"left": {"attempts": 40, "successes": 12, "success_rate": 30.0},
"right": {"attempts": 25, "successes": 5, "success_rate": 20.0},
"total": 17
}
},
"team_b": { "..." : "..." },
"score": {
"team_a": 41.24,
"team_b": 33.10,
"winner": "A"
}
}
可视化建议(前端)
- 左右边路对比雷达图:突破次数、成功率、传中
- 双队柱状图:左/右两侧分别对比
- 热力图:边路活跃区域
- 综合评分卡片:直观展示谁更强
可选增强
- 按分位加权:突破发生在禁区附近加权更高。
- 对手强度校正:用对手防守数据做归一化。
- 球员级下钻:追加
GROUP BY player_id,看核心边路是谁。 - 缓存层:结果存入 Redis,避免频繁聚合。
- 滚动窗口:
lastN支持季节窗口,剔除老数据。
需要我继续补充以下哪部分?
- 前端图表(ECharts)完整示例
- 球员级下钻代码
- 数据抓取(第三方 API 接入)方案
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播