2012-03-02 252 views
0

我有这段代码可以从表中选择所有用户,另一个sql语句可以统计每个用户的记录数。我面临的问题是,我有一个foreach循环中的sql,这对性能不利,但我无法在一个语句中将它们结合起来。任何建议?提高SQL语句的速度

$query = $db->getAll("SELECT * FROM users"); 
foreach($query as $v){ 
    $tpl->setCurrentBlock('useri'); 
    $query2 = $db->numRows("SELECT * FROM signups AS s INNER JOIN users AS u ON s.userid=u.id WHERE u.id={$v['id']}"); 
    $tpl->setVariable('total',$query2); 
    $tpl->setVariable($v); 
    $tpl->parseCurrentBlock(); 
} 
+0

你使用的是框架吗? – Joseph 2012-03-02 07:57:44

+0

请包含用户表和注册表的表结构。 – Kenny 2012-03-02 07:58:22

回答

3

尝试此查询对你的DB:

SELECT u.id, COUNT(s.*) 
    FROM users u 
    LEFT JOIN signups s ON s.userid = u.id 
    GROUP BY u.id 

我希望我是正确的。我没有SQL DB在这里测试它。重要提示:您必须按照您选择的没有聚合的每个字段进行分组。

编辑:

如果它不够快呢,上signups.userid索引可以帮助。然而,这是假设,所以你应该检查你的查询引擎生成的执行计划。

+0

我刚刚在我的一个数据库上测试了它,它工作正常。 – treeface 2012-03-02 08:02:35

+0

就是这样,谢谢 – user1164474 2012-03-02 08:03:17

+0

我有一个indexups.userid查询花了0.0009秒 – user1164474 2012-03-02 08:13:25

0

如果我理解你的问题很好,初始化变量并在循环中增加它。

int i; 
foreach($query as $v){ 
$tpl->setCurrentBlock('useri'); 
$query2 = $db->numRows("SELECT * FROM signups AS s INNER JOIN users AS u ON s.userid=u.id WHERE u.id={$v['id']}"); 
$tpl->setVariable('total',$query2); 
$tpl->setVariable($v); 
$tpl->parseCurrentBlock(); 
i++; 
} 
+0

我想移动sql语句ouside循环,因为如果我有1000k查询,它会花费很长时间 – user1164474 2012-03-02 08:00:28

+0

当然,我忘了删除第二个查询.. – yen1k 2012-03-02 08:04:46

1
$query = $db->getAll(" 
    SELECT u.id, u.name, COUNT(*) total 
    FROM signups AS s RIGHT JOIN users AS u ON s.userid=u.id 
GROUP BY u.id, u.name 
ORDER BY u.name 
"); 

foreach($query as $v){ 
    $tpl->setCurrentBlock('useri'); 
    $tpl->setVariable('total', $query['total']); 
    // ... 
    $tpl->parseCurrentBlock(); 
} 
+0

请记住,'INNER JOIN'省略'用户'行而没有相应的'signups',而不是将它们计数为零。 – 2012-03-02 08:09:23

+0

@Mudu你是对的。固定。 – Tomalak 2012-03-02 08:13:23