【问题标题】:Why do i get a cartesian product instead of join?为什么我得到笛卡尔积而不是加入?
【发布时间】:2011-06-11 11:53:58
【问题描述】:

下面的代码应该返回我游戏中前五名玩家的平均数。

SELECT "Starting 5" as Flag, 
       count(gs.ID) as Games, 
       avg(s.min) as Min, 
       avg(s.P2M) as P2M, 
       avg(s.P2A) as P2A, 
       100*avg(s.P2M/s.P2A) as P2P,  
       avg(s.P3M) as P3M,  
       avg(s.P3A) as P3A,  
       100*avg(s.P3M/s.P3A) as P3P,  
       avg(s.FTM) as FTM,  
       avg(s.FTA) as FTA,  
       100*avg(s.FTM/s.FTA) as FTP,  
       avg(s.OFFENSE) as OFFENSE,  
       avg(s.DEF) as DEF,  
       avg(s.TOT) as TOT,  
       avg(s.AST) as AST,  
       avg(s.TO) as 'TO',  
       avg(s.ST) as ST,  
       avg(s.FV) as FV,  
       avg(s.CM) as CM,  
       avg(s.PTS) as PTS,  
       avg(s.P2M - s.P2A + s.P3M - s.P3A + s.FTM - s.FTA + s.TOT + s.AST + s.ST + s.FV + s.PTS - s.TO - s.CM) as EFF  
FROM gamesstats AS gs 
    INNER JOIN gamesstatsplayers as gp ON gs.id=gp.GameStatID 
    INNER JOIN players as p ON gp.PlayerID = p.ID 
    INNER JOIN stats as s ON gp.stat=s.id 
                         WHERE gs.HomeTeamID ='664' 
                         and gs.HomeScore > gs.VisitorScore 
                         and gp.IsHomePlayer = 1 
                         AND gp.IsFirst5 = 1 
                         AND gs.SeasonStart = '2010' 
                         AND gs.LeagueID = '145' 

我应该得到 4 场比赛以及每场比赛的平均值。我得到的是游戏中每个玩家的平均值。这意味着我得到了 20 场比赛,每场比赛都是我想要的平均水平的 1/5。问题是由于某种原因它产生了笛卡尔积而不是连接。花了几个小时试图找到错误,但似乎找不到。

表格说明:

gamesstats 用于举办每场比赛。

gamesstatsplayers 通过 GameStatID 连接到游戏,并负责每个游戏中的每个玩家统计信息。

players 是所有玩家的表格。

stats 是一个只包含统计数据的表格,gamesstats 有一个统计数据链接,可以为您提供整个球队在一场比赛中的统计数据(2 个链接,一个用于主场,一个用于访客),gamesstatsplayers 有一个指向统计数据的链接为您提供 1 场比赛中 1 名球员的统计数据。 (这意味着 stats 用于两件事)。

【问题讨论】:

  • 可以添加一些架构信息吗?
  • 如果您包含 DDL 和示例数据(作为 INSERT 语句),则更容易提供帮助。我们大多数人都有时间回答问题。我们大多数人没有时间对您的查询进行逆向工程以得出可能是您的架构,然后我们自己生成示例数据。

标签: php mysql


【解决方案1】:

在不知道架构的情况下,这是一个猜测,但如果 GameStatID 是游戏的主键,您可能需要对其进行分组。

【讨论】:

  • 不,你没有正确理解我想要什么。我不想要 4 行的平均值,我想要 1 行的平均值。
  • @Vadiklk:你在描述中说,你想要“我应该得到 4 场比赛以及每场比赛的平均值”。所以,试试这个建议,在查询末尾添加GROUP BY gs.id
  • 我的意思是“游戏”应该返回 4 并且平均值应该是游戏中的平均值。一排。
【解决方案2】:

首先,你应该使用 WHERE 子句:

SELECT "Starting 5" as Flag, 
       count(gs.ID) as Games, 
       avg(s.min) as Min, 
       avg(s.P2M) as P2M, 
       avg(s.P2A) as P2A, 
       100*avg(s.P2M/s.P2A) as P2P,  
       avg(s.P3M) as P3M,  
       avg(s.P3A) as P3A,  
       100*avg(s.P3M/s.P3A) as P3P,  
       avg(s.FTM) as FTM,  
       avg(s.FTA) as FTA,  
       100*avg(s.FTM/s.FTA) as FTP,  
       avg(s.OFFENSE) as OFFENSE,  
       avg(s.DEF) as DEF,  
       avg(s.TOT) as TOT,  
       avg(s.AST) as AST,  
       avg(s.TO) as 'TO',  
       avg(s.ST) as ST,  
       avg(s.FV) as FV,  
       avg(s.CM) as CM,  
       avg(s.PTS) as PTS,  
       avg(s.P2M - s.P2A + s.P3M - s.P3A + s.FTM - s.FTA + s.TOT + s.AST + s.ST + s.FV + s.PTS - s.TO - s.CM) as EFF  
FROM gamesstats AS gs 
    INNER JOIN gamesstatsplayers as gp ON gs.id=gp.GameStatID 
    INNER JOIN players as p ON gp.PlayerID = p.ID 
    INNER JOIN stats as s ON gp.stat=s.id 
    WHERE
     gs.HomeTeamID ='664' 
     and gs.HomeScore > gs.VisitorScore 
     and gp.IsHomePlayer = 1 
     AND gp.IsFirst5 = 1 
     AND gs.SeasonStart = '2010' 
     AND gs.LeagueID = '145' 

【讨论】:

  • 我用过,这里写的时候误删了。然而,这不是错误。
猜你喜欢
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多