You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CodeIgniter中高效按月份统计用户登录数据?

优化CodeIgniter中按月统计用户登录次数的方案

你的思路完全没错,重复写每个月份的查询方法确实太冗余了,不仅维护麻烦,新增月份还要修改Model代码。下面给你两种更优的实现方式,解决你的问题:

方案1:通用单月统计方法

先在Model中写一个通用方法,接收年份和月份作为参数,自动计算当月的起止日期并统计:

public function getMonthlyLoginCount($year, $month) {
    // 自动生成当月第一天和最后一天
    $startDate = date("$year-$month-01");
    $endDate = date("$year-$month-t"); // 't'会自动返回当月的天数,不用手动处理2月的28/29天
    
    $this->db->where('Date >=', $startDate);
    $this->db->where('Date <=', $endDate);
    return $this->db->count_all_results('user_data');
}

然后在Controller中调用这个方法即可,不用再写多个重复的赋值:

public function index(){
    $targetYear = 2018;
    $data["april"] = $this->login_model->getMonthlyLoginCount($targetYear, 4);
    $data["march"] = $this->login_model->getMonthlyLoginCount($targetYear, 3);
    $data["february"] = $this->login_model->getMonthlyLoginCount($targetYear, 2);
    
    $this->load->view('main/header');
    $this->load->view('main/body', $data);
    $this->load->view('main/footer');
}

View代码可以保持不变,依然直接输出对应的变量。

方案2:一次性查询全年(或指定时间段)的统计数据(更推荐)

如果需要统计多个月份,多次查询数据库会影响性能,我们可以用GROUP BY结合日期函数一次性获取所有月份的统计结果,这才是你之前尝试group_by的正确打开方式:

Model代码

public function getYearlyLoginCounts($year = 2018) {
    // 选择月份和对应的登录次数
    $this->db->select('MONTH(Date) as month_num, COUNT(*) as login_count');
    // 过滤指定年份的数据
    $this->db->where('YEAR(Date)', $year);
    // 按月份分组
    $this->db->group_by('month_num');
    // 按月份排序
    $this->db->order_by('month_num', 'ASC');
    
    return $this->db->get('user_data')->result_array();
}

Controller代码

把查询结果处理成View更容易调用的格式,同时处理没有数据的月份(默认设为0):

public function index(){
    $targetYear = 2018;
    $monthlyStats = $this->login_model->getYearlyLoginCounts($targetYear);
    
    // 转换为以月份名称为键的数组(比如'february' => 123)
    $data['monthly_data'] = [];
    foreach ($monthlyStats as $stat) {
        // 将数字月份转为小写英文名称
        $monthName = strtolower(date('F', mktime(0, 0, 0, $stat['month_num'], 1)));
        $data['monthly_data'][$monthName] = $stat['login_count'];
    }
    
    // 确保所有需要的月份都有值,没有的话设为0
    $requiredMonths = ['february', 'march', 'april'];
    foreach ($requiredMonths as $month) {
        if (!isset($data['monthly_data'][$month])) {
            $data['monthly_data'][$month] = 0;
        }
    }
    
    $this->load->view('main/header');
    $this->load->view('main/body', $data);
    $this->load->view('main/footer');
}

View代码

现在可以直接通过数组访问各个月份的数据:

<p><strong><?php echo $monthly_data['april']; ?></strong></p>
<p><strong><?php echo $monthly_data['march']; ?></strong></p>
<p><strong><?php echo $monthly_data['february']; ?></strong></p>

为什么你之前的group_by没得到正确结果?

你之前只写了$this->db->group_by('MONTH(Date)');,但没有指定要统计每个分组的数量,所以查询返回的是每个月份的原始记录,而不是计数。必须结合COUNT(*)来获取每个分组的记录总数,这才是分组统计的正确用法。

内容的提问来源于stack exchange,提问作者JasLamba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:09:24