下面的代码上线后会不会崩 Group by 会不会更好 比他们都好的是(除了单独表已经记录了数值)
// 初始化结果数组
$monthlyRecordCounts = [];
// 类型
$status = [
'2' => '已上编',
'3' => '已撤销',
'4' => '已作废'
];
// 循环 12 个月
for ($month = 1; $month <= 12; $month++) {
foreach ($status as $key => $value){
// 构造起始和结束日期
$startDate = date('Y-m-01', mktime(0, 0, 0, $month, 1, date('Y')));
$endDate = date('Y-m-t', mktime(0, 0, 0, $month, 1, date('Y')));
// 查询该月的记录数
$count = Db::name('bianzhidan_log')
->where('change_time', '>=', $startDate)
->where('change_time', '<=', $endDate)
->where('status', '=', $key)
->count();
// 将结果添加到数组中
$monthlyRecordCounts[$value][] = $count;
}
}
// 输出结果
print_r($monthlyRecordCounts);
1
Belmode 364 天前
不懂 php ,这么写,在数据量尚可的情况下肯定没有业务问题,只是看起来不够凝炼。
从开发惯性上来说,还是 group by 更合理一点。 |
2
yc8332 364 天前
那肯定不至于。就是慢点而已。
|
5
TiaoYeTaiLang 364 天前
一次性查 1 年的数据,和查 12 次 1 个月的数据,你觉得哪个对于数据库来说哪种方式是压力最分散的
|
6
5200 364 天前
一般不要在循环里面写 SQL
``` $monthlyRecordCounts = []; // 类型 $status = [ '2' => '已上编', '3' => '已撤销', '4' => '已作废' ]; // 循环 12 个月 for ($month = 1; $month <= 12; $month++) { // 构造起始和结束日期 $startDate = date('Y-m-01', mktime(0, 0, 0, $month, 1, date('Y'))); $endDate = date('Y-m-t', mktime(0, 0, 0, $month, 1, date('Y'))); // 查询该月的记录数 $queryResult = Db::name('bianzhidan_log') ->field('status, COUNT(*) as count') ->where('change_time', '>=', $startDate) ->where('change_time', '<=', $endDate) ->where('status', 'IN', array_keys($status)) ->group('status') ->select(); // 将结果添加到数组中 foreach ($queryResult as $result) { $statusKey = $result['status']; $monthlyRecordCounts[$status[$statusKey]][$month] = $result['count']; } } // 输出结果 print_r($monthlyRecordCounts); ``` |
7
Rache1 364 天前
你这 status 这里的完全可以用 where in ... group by 。
至于外部的按月份,我倒觉得没多大必要,因为像你现在这样按月进行汇总统计的,group by 的时候必然要把每一行数据都执行一下 date_format 才能得出 年+月,然后进行 group by 这样效率肯定不会很高。 如果只是偶尔使用,为了导出报表,那问题应该不大,如果作为业务功能的话,那只需要内部 where in ... group by ,外部就还是按月就好了。 另外就是,对于这种需求,如果访问比较频繁的话,最好的做法你自己也提到了,就是单独拿一张表来计数,或者在现有的基础上配合上缓存。 |
10
JackSlowFcck 364 天前
上线后的代码稳定性要看服务器和数据库,但用 GROUP BY 和加索引、缓存等方法,能让查询更高效,系统负担更小。
|
11
iseki 364 天前
你要是担心数据库 group by 构造月份比较慢,我倒是觉得你可以试试 select (里面放 12 个 select)😁
但我往往选择相信数据库( |
12
luoyou1014 364 天前
如果是 mysql8 的话,直接建虚拟字段 v_month ,值根据 change_time 自动生成,然后在 v_month 上建立索引,就可以直接 group('v_month', 'status'),直接得到结果。
ALTER TABLE `bianzhidan_log` ADD COLUMN `v_month` int UNSIGNED GENERATED ALWAYS AS (date_format(`change_time`, "%Y%m")) VIRTUAL 性能提升两个数量级,且代码量降低为原来 1/10 |
13
tlerbao OP @luoyou1014 可惜还是 5.7
|
14
luoyou1014 359 天前
|