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
只有 gid
和 name
。 gid
中的 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语句怎样使用才是有效的,我为啥不行的