计数:多个查询或一个包含多个子查询的查询?

时间:2011-12-06 08:58:43

标签: mysql codeigniter

我想制作一个摘要脚本,例如,今天,昨天,本周,上周,本月,上个月有多少新用户,等等。

我正在使用CodeIgniter,所以我想知道哪一个更好?在这样的模型上使用多个调用:

$this->model->get_today_users();
$this->model->get_yesterday_users();
$this->model->get_this_week_users();
// so on

上述每个函数仅返回具有特定日期范围的用户数(例如,对于today_users等的SELECT COUNT(*)WHERE join_date = NOW() - 当然使用CI活动记录)。

或者使用所有必需的子查询进行单个查询会更好:

function stats(){
$this->db->select('*');
$this->db->select('(SELECT COUNT(*) FROM users WHERE join_date=NOW()) as today');
$this->db->select('(SELECT COUNT(*) FROM users WHERE join_date=NOW()-INTERVAL 1 DAY) as yesterday');
$this->db->select('(SELECT COUNT(*) FROM users WHERE WEEK(join_date)=WEEK(NOW()) ) as this_week');
$this->db->select('(SELECT COUNT(*) FROM users WHERE WEEK(join_date)=WEEK(NOW())-1 ) as last_week');
$this->db->select('(SELECT COUNT(*) FROM users WHERE MONTH(join_date)=MONTH(NOW()) ) as this_month');
$this->db->select('(SELECT COUNT(*) FROM users WHERE MONTH(join_date)=MONTH(NOW())-1 ) as last_month');
$this->db->from('users');
$ret = $this->db->get();
}

然后调用例如$ data ['stat'] = $ this-> model-> stats();所以在视图中,我可以调用$ stat->今天,$ stat-> this_week等。

提前感谢您的答案。

更新:如果我想创建一个收到日期的函数怎么办?假设我必须像这样循环一个月:

//for the sake of simplicity
foreach(day in a month as $r){
    $this->model->get_user_on_this_day($r);
}

这意味着每月30天,它将循环30次!还有比这更好的方法吗?

5 个答案:

答案 0 :(得分:1)

正确答案可能是:它取决于。从代码可重用性和可读性的角度来看,第一个选项可能更好。另一方面,第二个选项意味着您只联系数据库而不是三次。所以后者可能会在性能上更好,因为这意味着你只需要一次联系数据库,这意味着只有一个连接,一个事务等。对于大型数据库,连接速度慢等,这意味着更快的结果。

答案 1 :(得分:0)

您是否考虑使用您提到的第二个选项在您的用户表上创建视图?您的查询只有一个执行计划,只有在主表中的数据发生更改时才会处理它。而且您只需要一个简单的查询即可获得所需内容。

如果您需要添加更多计数,如上所述,您只需在视图中添加列。

答案 2 :(得分:0)

IMO,这两种方法都没有得到优化 使用最少查询是最好的,因此,您应该执行如下的GROUP BY查询:

select date_format(join_date, '%Y-%m-%d') as the_date, count(*) as total
from users
where join_date between $start AND $end   <-- the date range
group by the_date;

获得结果后,您可以使用日期作为键设置数组,
然后你可以按日,周,月......进一步分组......(无论你想要什么)


似乎OP不明白这是如何工作的: -

以上查询正在执行一次性查询,并将返回

之类的行
2011-12-09, 20 users join
2011-12-08, 10 users join
2011-12-07, 51 users join
...

您所要做的就是迭代结果(不是活动记录)

$query = $this->db->query($sql, array($start, $end));
$rtn   = array();
$total = 0;
foreach ($query->result() as $row)
{
  $rtn[$row->the_date] = $row->total;
  $total += $row->total;
}

在循环结束时,$ total =从$ start注册到$ end的总用户数。

更有效并优化,然后在月 - 日循环期间执行30(或31)次查询。

答案 3 :(得分:0)

一种方法是,能够在一个查询中使用您的第一个选项,将有一个初始化命令。

$this->model->buildmodel();

你可以将数周,月,日ETC的记录保存在一个数组中,然后你可以调用它,这意味着它可以轻松定制,并且速度更快,只需一个查询。

答案 4 :(得分:0)

您应该使用单独的查询并缓存给定日期的结果,因此您不必多次查询。

由于人们过去无法加入,因此给定查询(当天除外)的数据永远不会改变。