【问题标题】:Wrong result of mysql query - where is the mistake?mysql查询的错误结果-错误在哪里?
【发布时间】:2020-12-17 07:20:27
【问题描述】:

我的 mysql 查询有问题。查询结果显示足球队的统计数据。问题:如果一名球员在一场比赛中进了 2 个球,则计算 2 次“首发”而不是 1 次“首发”。如果一名球员在一场比赛中进了 3 个球,那么我的查询会计算 3 个“首发”而不是 1 个“首发”。

请帮忙看看问题出在哪里,我不知道: 这是Mysql查询:

'SELECT '.TBL_PERSONS.'.id AS id_person, '.TBL_PERSONS.'.firstname AS firstname, '.TBL_PERSONS.'.lastname AS lastname,
count(case when '.TBL_LINEUP.'.type = 2 then 1 else NULL end) AS starter,
sum(case when '.TBL_LINEUP.'.type = 3 then 1 else 0 end) AS bench,
sum(case when GOALS.id_person = '.TBL_LINEUP.'.id_person then 1 else 0 end) AS goal,
sum(case when ASSIST.assist_id = '.TBL_LINEUP.'.id_person then 1 else 0 end) AS assist
FROM '.TBL_LINEUP.'

JOIN '.TBL_MATCHS.' ON '.TBL_LINEUP.'.id_match = '.TBL_MATCHS.'.id AND 
'.TBL_MATCHS.'.id_season = "2" AND '.TBL_MATCHS.'.id_compet = "2" AND '.TBL_MATCHS.'.validation = "1"

JOIN '.TBL_PERSONS.' ON '.TBL_LINEUP.'.id_person = '.TBL_PERSONS.'.id

LEFT JOIN '.TBL_GOALS.' AS GOALS  ON '.TBL_LINEUP.'.id_person = GOALS.id_person AND '.TBL_MATCHS.'.id = GOALS.id_match AND GOALS.goal_csc = 0

LEFT JOIN '.TBL_GOALS.' AS ASSIST ON 
'.TBL_LINEUP.'.id_person = ASSIST.assist_id AND '.TBL_LINEUP.'.id_match = ASSIST.id_match

WHERE '.TBL_LINEUP.'.id_club = 36
GROUP BY id_person';

如果我删除目标的左连接

LEFT JOIN '.TBL_GOALS.' AS GOALS  ON '.TBL_LINEUP.'.id_person = GOALS.id_person AND '.TBL_MATCHS.'.id = GOALS.id_match AND GOALS.goal_csc = 0

那么查询的结果看起来不错。

数据库结构:

tbl_lineup:id、id_match、id_club、id_person、类型

tbl_persons: id、姓氏、名字

tbl_matchs: id_candidate_dom、id_candidate_ext、id_season、id_compet

tbl_goals: id,id_match,id_person,id_club,goal_min,goal_csc(0个正常进球,1个乌龙球),goal_pen(0个不进球,1个罚球),assist_id(进球的球员ID协助)

请帮助我,因为我不知道我的查询有什么问题。非常感谢。

【问题讨论】:

  • 样本数据会有所帮助。
  • 如果一名球员在一场比赛中进了 2 个球,则计算 2 次“首发”而不是 1 次“首发”。您必须计算不同的比赛数量,其中type = 2 . IE。类似COUNT(DISTINCT CASE WHEN tbl_lineup.type = 2 THEN tbl_matchs.id END).
  • @Liverpool 请您在edit 您的问题中包含minimal reproducible example - 一组表定义和示例数据、一个没有任何占位符的完整 SQL 查询以及当前和所需的输出。这有助于避免需求中的歧义,并意味着我们可以在发布之前测试可能的解决方案。
  • @IMSoP 我必须确保提供的方法可以解决问题。在目前的状态下,我无法确定——所以我使用注释表(并要求提供最终的 SQL 代码)来解释主要方式。
  • @Akina 但是现在你已经为 OP 提供了他们需要的东西,所以现在或将来没有动力让他们写出更好的问题。他们得到了他们想要的东西,但网站只剩下一半的问题和一半的答案。我希望我在这种情况下是错的,但一般原则是:cmets 中的答案对整个网站都是不利的。

标签: php mysql sql join


【解决方案1】:

您的查询使用下一个表达式:

count(case when '.TBL_LINEUP.'.type = 2 then 1 else NULL end) AS starter

此表达式计算进球数,不区分进球数。

您需要计算的不是进球本身,而是进球的比赛。每个目标都必须替换为唯一的游戏标识符,并且必须计算不同标识符的数量。

所以代码可能看起来像

COUNT(DISTINCT CASE WHEN tbl_lineup.type = 2 THEN tbl_matchs.id END) AS starter

如果在不同的比赛中打进 2 个进球,则将计算 2 个不同的ids。但是如果在同一场比赛中进了 2 个球,那么将产生 2 个相等的 ids,并且 DISTINCT 只会计算一次。

type != 2 的行将产生 NULL,因为 CASE 没有 ELSE 部分,因此它们将被 COUNT() 忽略。如果你想为没有进球的球员(?)获得零而不是 NULL,然后用 COALESCE() 包装表达式,即

COALESCE(COUNT(DISTINCT CASE WHEN tbl_lineup.type = 2 THEN tbl_matchs.id END), 0) AS starter

【讨论】: