我有一个MySQL查询:
在我看来,这段代码可能要小得多。我该如何缩小这个查询。 http://sqlfiddle.com/#!2/6d211/1
即使您只是给我链接签出,任何帮助都会受到赞赏。
答案 0 :(得分:1)
通常,最好将连接逻辑作为[Inner|Left] Join
子句的一部分,而不是Where
子句的一部分。在简化查询的情况下,这会清除您的Where子句,以便查询处理器不会过早应用过滤条件,从而限制您在查询的更复杂部分中要执行的操作(并影响查询的整体性能)查询)。
通过重构连接条件,我们可以将查询减少到三个表中的核心连接,然后将连接添加到发生聚合的专用子查询中。这导致只有一个嵌套查询,它连接所需的最少表。
以下是我提出的建议:
SELECT
u.user_id
,pg.game_id
,u.user
,g.game
,g.game_cat
,ga.cat_count
,ga.fps_count
FROM users u
inner join played_games pg
on u.user_id = pg.user_id
inner join games g
on pg.game_id = g.id
inner join
(
select
ipg.user_id
,ig.game_cat
,count(ig.game) cat_count
,sum(case when ig.game_cat = 'fps' then 1 else 0 end) fps_count
from played_games ipg
inner join games ig
on ipg.game_id = ig.id
group by
ipg.user_id
,ig.game_cat
) ga
on g.game_cat = ga.game_cat
and pg.user_id = ga.user_id
order by
ga.fps_count desc
,u.user
,ga.cat_count desc;
原始查询(除了轻微重命名)之间的一个区别是,对于没有玩过单个FPS游戏的玩家,fps_count字段的值为0而不是NULL。希望这不是那么重要,而是有助于为查询添加含义。
最后,我不确定如何使用它的背景。在我看来,它可能试图在列出每个用户玩的每个游戏(一个目标)和总结每个用户玩的游戏类别(一个单独的目标)方面做太多。这意味着摘要细节被重复多次,例如,对于玩特定类别的多个游戏的用户而言,这可能并不理想。我的建议是将这些问题分成两个单独的查询,但我不知道这是否符合您的具体需求。
希望这有帮助。
答案 1 :(得分:0)
我在考虑是否提供d_mcg解决方案或者这个解决方案。我决定去找这个。我想知道哪一个会更快。这是你可以试着告诉我们的事情:)
select u.user_id, pg.game_id, u.user, g.game, g.game_cat,
(select count(*) from played_games pg2
join games g2 on pg2.game_id = g2.id
where pg2.user_id = pg.user_id and g2.game_cat = g.game_cat) cat_count,
(select count(*) from played_games pg3
join games g3 on pg3.game_id = g3.id
where pg3.user_id = pg.user_id and g3.game_cat = g.game_cat and
g.game_cat = 'fps') order_count
from users u
left join played_games pg on u.user_id = pg.user_id
join games g on pg.game_id = g.id
order by order_count desc, u.user, cat_count desc