SQL,努力相信 HAVING 可以比连接更有效

Posted

技术标签:

【中文标题】SQL,努力相信 HAVING 可以比连接更有效【英文标题】:SQL, Struggling to believe HAVING can be more efficient than a join 【发布时间】:2013-02-05 03:46:45 【问题描述】:

我正在尝试在下表中查找曾为一支球队参加过一场以上比赛的球员(** 表示私钥),并且很难相信我能想到的最佳查询(如下)是最有效的。关于如何改进它的想法,以及为什么会非常感谢的解释(尝试学习 SQL)

Team (*tid*, name)
Game (*gid*, tid)
Player (*gid*, *name*)

SELECT Team_Name, Player_Name

  FROM (SELECT GID, TID FROM GAME) G
      ,(SELECT NAME AS Player_Name, GID FROM PLAYER) P
      ,(SELECT NAME AS Team_Name, TID FROM TEAM) T

  WHERE (     G.GID = P.GID
          AND Player_Name IN (SELECT P.NAME
                                FROM GAME G
                                    ,PLAYER P
                                WHERE G.GID = P.GID
                                GROUP BY P.NAME
                                HAVING COUNT(P.NAME) > 1)
          AND T.TID = G.TID
        )

  GROUP BY Team_Name, Player_Name
  HAVING COUNT(Player_Name) > 1
  ORDER BY Team_Name

【问题讨论】:

您能给我们提供样本数据和预期输出以便更好地理解吗?另外,我认为桌子设计有点错误。 Player 只有 gidnamegid 中的 game 可以有两个团队。所以player.gid 将保持不变,而game.tid 中的团队可能不同。如果玩家名字相同,就会出现更多问题。 Player里面还有一个PID字段,还有一个MEMBEROF Table。由于查询没有必要,因此我将它们排除在外。规范指出,没有两个玩家会有相同的名字,我可能应该包括在内。回首往事,我可以看到混乱的可能性!想法是列出所有参加过两场比赛的球员以及他们效力的球队(所以这包括任何转会等,他们必须参加过两场比赛,但不一定是同一支球队 【参考方案1】:

您是在询问哪些玩家参加过不止一场比赛。

SELECT P.Player_Name
FROM Player P
GROUP BY P.Player_Name
HAVING COUNT(DISTINCT P.GID) > 1

这将返回所有玩过 1 场以上游戏 (GID) 的玩家。

如果您还想 GROUP BY 团队,请执行以下操作:

SELECT P.Player_Name, T.Team_Name
FROM Player P
    JOIN Game G ON P.GID = G.GID
    JOIN Team T ON G.TID = T.TID
GROUP BY P.Player_Name, T.Team_Name
HAVING COUNT(DISTINCT G.GID) > 1

在 Player 表中包含 GID 似乎很奇怪。也许拥有一个存储 PlayerId 和 GameId 的 PlayerGames 表会更有意义——更好地进行数据库规范化。 Player 表应该只为每个玩家存储一条记录。

另外,球员和球队之间真正的联系是什么。在这种情况下,您是说玩家必须玩游戏,而游戏必须有一个团队(或者一个游戏应该有 2 个或更多团队)。让我们知道您的目标,我们可以帮助您提出最佳选择。

祝你好运。

【讨论】:

谢谢,如果您看到我对原始帖子的评论以回应 Orangecrush,我意识到我应该更好地解释一些事情。 GROUP BY 查询完全符合我的要求(即与我的相同),但不幸的是,它的效率似乎低于原始查询。这是真正的问题,我很难相信原版是最有效的,但想不出比这更好的了! 不确定我是否在关注您-这些查询是您最有效的...您的原始查询一团糟:)您有多个 GROUP BY、多个表扫描等...可能是最适合您使用示例 (sqlfiddle.com) 构建 SQL Fiddle。更糟糕的情况是,使用我的第一个查询(没有比它更有效的)并使用 PlayerId IN ()。祝你好运。 我正在通过 aqua data studio 在 Oracle 数据库上运行查询。执行计划建议我发布的查询的节点成本为 10,而不是您的 11。原版也使用了相当少的内存。这就是我首先发布的原因,据我所知,我同意您使用的连接方法(并且我之前尝试过)应该更有效,但它似乎是 DBMS 处理它的方式,它不是!

以上是关于SQL,努力相信 HAVING 可以比连接更有效的主要内容,如果未能解决你的问题,请参考以下文章

如何可以更好的培养大家的创新思维能力

group by后接的having语句怎样使用才是有效的,我为啥不行的

SQL on&where&having

mysql经常使用查询:group by,左连接,子查询,having where

在连接表语句中访问 SQL 多个 HAVING

使用空数据集的Spark SQL连接会导致更大的输出文件大小