PHP项目统计红黄牌数量哪队更多
下面给你一个完整的实现思路和代码示例。

数据表结构设计
CREATE TABLE match_cards (
id INT AUTO_INCREMENT PRIMARY KEY,
match_id INT NOT NULL COMMENT '比赛ID',
team_id INT NOT NULL COMMENT '球队ID',
team_name VARCHAR(50) NOT NULL COMMENT '球队名称',
card_type ENUM('yellow','red') NOT NULL COMMENT '牌类型',
player_name VARCHAR(50) COMMENT '球员名',
minute INT COMMENT '发生分钟',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
核心统计逻辑(PDO 示例)
<?php
// db.php 数据库连接
$pdo = new PDO('mysql:host=localhost;dbname=football;charset=utf8mb4', 'root', 'password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
/**
* 统计指定比赛(或全部比赛)各队红黄牌数量
* @param PDO $pdo
* @param int|null $matchId 传 null 表示统计全部
* @return array
*/
function getCardStats(PDO $pdo, ?int $matchId = null): array
{
$sql = "
SELECT
team_id,
team_name,
SUM(card_type = 'yellow') AS yellow_count,
SUM(card_type = 'red') AS red_count,
COUNT(*) AS total_count,
-- 加权分:黄牌1分,红牌2分(可按业务调整)
SUM(card_type = 'yellow') * 1 + SUM(card_type = 'red') * 2 AS score
FROM match_cards
";
$params = [];
if ($matchId !== null) {
$sql .= " WHERE match_id = :match_id";
$params[':match_id'] = $matchId;
}
$sql .= " GROUP BY team_id, team_name ORDER BY score DESC, red_count DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
/**
* 判断哪队红黄牌更多
* @param array $stats getCardStats 的返回
* @return array
*/
function compareCards(array $stats): array
{
if (count($stats) < 2) {
return ['winner' => null, 'message' => '数据不足,无法比较'];
}
$first = $stats[0];
$second = $stats[1];
// 完全一样的情况
if ($first['score'] == $second['score']
&& $first['yellow_count'] == $second['yellow_count']
&& $first['red_count'] == $second['red_count']) {
return [
'winner' => null,
'message' => "两队牌数相同:{$first['team_name']} 与 {$second['team_name']}"
];
}
return [
'winner' => $first['team_name'],
'message' => sprintf(
'%s 牌更多(黄牌%d张/红牌%d张,加权%d分),比 %s 多 %d 分',
$first['team_name'],
$first['yellow_count'],
$first['red_count'],
$first['score'],
$second['team_name'],
$first['score'] - $second['score']
),
'detail' => $stats,
];
}
// ====== 使用示例 ======
$matchId = 1001; // 传 null 统计全部比赛
$stats = getCardStats($pdo, $matchId);
$result = compareCards($stats);
print_r($stats);
echo $result['message'] . PHP_EOL;
输出示例
Array
(
[0] => Array
(
[team_id] => 1
[team_name] => 主队A
[yellow_count] => 4
[red_count] => 1
[total_count] => 5
[score] => 6
)
[1] => Array
(
[team_id] => 2
[team_name] => 客队B
[yellow_count] => 2
[red_count] => 0
[total_count] => 2
[score] => 2
)
)
主队A 牌更多(黄牌4张/红牌1张,加权6分),比 客队B 多 4 分
关键点说明
| 要点 | 说明 |
|---|---|
| 计数方式 | 用 SUM(card_type='yellow') 技巧,MySQL 中布尔值即 0/1,避免多次 COUNT 子查询 |
| 比较标准 | 直接比"总牌数"往往不合理(1红 vs 3黄),建议用加权分(黄1分/红2分),可按业务调整 |
排序 ORDER BY |
先按加权分 DESC,再按 red_count DESC,确保红牌多者靠前 |
| 平局处理 | 分数、黄牌、红牌全部相等时判定为平局 |
| 性能 | 给 match_id、team_id 建索引;大表可加 card_type 联合索引 |
进阶:按赛事/赛季统计
// 只统计某个赛季或联赛
$sql = "
SELECT t.team_name,
SUM(c.card_type='yellow') AS yellow,
SUM(c.card_type='red') AS red
FROM match_cards c
JOIN matches m ON m.id = c.match_id
JOIN teams t ON t.id = c.team_id
WHERE m.season = :season
GROUP BY c.team_id
ORDER BY (red*2 + yellow) DESC
LIMIT 10
";
这样就可以灵活地输出「红黄牌最多/最少的球队排行榜」。
如果你有具体的数据表结构或需要 Laravel / ThinkPHP 版本的写法,可以把字段发我,我帮你改造成对应框架的查询构造器版本。