2010-10-11 56 views
0

这里是我当前的查询:一些严重的SQL查询优化需要(MySQL的)

SELECT IFNULL(sum(open_for), 0) total, count(IF(open_for > 0, 1, null)) wins, count(IF(open_for < 0, 1, null)) losses FROM `sport_points` WHERE (sportable_id = 1 and sportable_type = 'Team' and game_time > '2010-07-13 11:39:58 UTC' 

它基本上返回这些汇总数据:

  • open_for
  • 总:2000
  • 获胜:20
  • 损失:12

现在,假设表中有大约6个其他列,我需要执行单独的查询以获得一个团队的所有特定于列的聚合数据。例如:

SELECT IFNULL(sum(FINAL_FOR), 0) total, count(IF(open_for > 0, 1, null)) wins, count(IF(open_for < 0, 1, null)) losses FROM `sport_points` WHERE (sportable_id = 1 and sportable_type = 'Team' and game_time > '2010-07-13 11:39:58 UTC' 

TEAM甲

  • final_for
  • 总数:4000
  • 胜:40
  • 损失:18

这种方法的问题在于我必须针对所有列运行大约6次单独的查询200支队伍。这是一个严重的负载问题。

理想情况下,查询将返回一个团队的所有特定于列的聚合数据 - 在一个查询中。它看起来像这样的结果:

  • open_for_total
  • open_for_wins
  • open_for_losses
  • final_for_total
  • final_for_wins
  • final_for_losses

...等...

+0

6个单独的查询我可以理解,但似乎这些查询可以按团队ID进行分组,因此您可以在6个不同的查询中获得所有200个团队的结果。 6个查询不应该对200个团队造成负载问题。你是否正确编制了表格索引? – methodin 2010-10-11 11:59:54

+0

该方法可能工作...但是,我并不总是想要所有200个团队一次...不管,它可能是一个选项...什么是SQL的样子? – keruilin 2010-10-11 12:09:06

回答

0

只是对于那些谁想要帮助的好处:

查询1:

SELECT 
    IFNULL(sum(open_for), 0) total 
    ,COUNT(IF(open_for > 0, 1, null)) wins 
    ,COUNT(IF(open_for < 0, 1, null)) losses 
FROM 
    `sport_points` 
WHERE 
    sportable_id = 1 
    AND sportable_type = 'Team' 
    AND game_time > '2010-07-13 11:39:58 UTC' 

查询2:

SELECT 
    IFNULL(SUM(FINAL_FOR), 0) total 
    ,COUNT(IF(open_for > 0, 1, null)) wins 
    ,COUNT(IF(open_for < 0, 1, null)) losses 
FROM 
    `sport_points` 
WHERE 
    sportable_id = 1 
    AND sportable_type = 'Team' 
    AND game_time > '2010-07-13 11:39:58 UTC' 

所需的输出列:teamname,typeofquery,价值

其中typeofquery是以下之一:

  • open_for_total
  • open_for_wins
  • open_for_losses
  • final_for_total
  • final_for_wins
  • final_for_losses

从两列open_forfinal_for结合衍生与winslosses式柱纳秒。

最初考虑问题我猜中间表可能会帮助处理GROUP BY子句。

例如

INSERT INTO 
    temptable 
SELECT 
    teamname 
    ,'open_for' type 
    ,IFNULL(SUM(open_for), 0) total 
    ,COUNT(IF(open_for > 0, 1, null)) wins 
    ,COUNT(IF(open_for < 0, 1, null)) losses 
FROM 
    `sport_points` 
WHERE 
    sportable_id = 1 
    AND sportable_type = 'Team' 
    AND game_time > '...' 
GROUP BY 
    teamname 

然后运行相同的查询但求和final_for。现在,您的临时表包含类似行:根据需要

teamname, type, total, wins, losses 
TEAM A, open_for, 100, 37, 63 
TEAM A, final_for, 30, 10, 20 
TEAM B, open_for, 12, 8, 4 
TEAM B, final_for, 50, 49, 1 

你最终的查询可能正好连接列。

0

我会这样做作为一个单一的查询,它为每个统计返回单独的。如果有必要,我会在我的应用程序代码中重构结果。该查询看起来像这样:

select teamname, 
sum(open_for) as open_total, 
count(if(open_for > 0, 1, null)) as open_wins, 
count(if(open_for < 0, 1, null)) as open_losses, 
sum(final_for) as final_total, 
count(if(final_for > 0, 1, null)) as final_wins, 
count(if(final_for < 0, 1, null)) as final_losses, 
from sport_points 
where sportable_id = 1 
and sportable_type = 'Team' 
and game_time > '...' 
group by teamname 

这,我建议,是一种更正统的关系方法,所以很容易用SQL表示。如果它不是您的应用程序所需的,那么调整的地方就是代码,这比SQL更灵活。

+0

如果你喜欢,你可以很容易地将它限制在一个小组的子集(或者甚至是行,不管那些对应的行) - 你只需像往常一样向where子句添加条件。 – 2010-10-11 13:52:41