这样的代码上线后会不会崩, GROUP BY 会不会更好或更好的办法是?

134 天前
 tlerbao

下面的代码上线后会不会崩 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);
1746 次点击
所在节点    程序员
14 条回复
Belmode
134 天前
不懂 php ,这么写,在数据量尚可的情况下肯定没有业务问题,只是看起来不够凝炼。
从开发惯性上来说,还是 group by 更合理一点。
yc8332
134 天前
那肯定不至于。就是慢点而已。
tlerbao
134 天前
@yc8332 如果是您您会怎么写?
tlerbao
134 天前
@Belmode 听说 group by 也很影响效率
TiaoYeTaiLang
134 天前
一次性查 1 年的数据,和查 12 次 1 个月的数据,你觉得哪个对于数据库来说哪种方式是压力最分散的
5200
134 天前
一般不要在循环里面写 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);

```
Rache1
134 天前
你这 status 这里的完全可以用 where in ... group by 。

至于外部的按月份,我倒觉得没多大必要,因为像你现在这样按月进行汇总统计的,group by 的时候必然要把每一行数据都执行一下 date_format 才能得出 年+月,然后进行 group by 这样效率肯定不会很高。

如果只是偶尔使用,为了导出报表,那问题应该不大,如果作为业务功能的话,那只需要内部 where in ... group by ,外部就还是按月就好了。


另外就是,对于这种需求,如果访问比较频繁的话,最好的做法你自己也提到了,就是单独拿一张表来计数,或者在现有的基础上配合上缓存。
tlerbao
134 天前
@Rache1 没听太明白呢,愿闻其详小哥
Rache1
134 天前
@tlerbao #8 6 楼已经有代码了
JackSlowFcck
134 天前
上线后的代码稳定性要看服务器和数据库,但用 GROUP BY 和加索引、缓存等方法,能让查询更高效,系统负担更小。
iseki
134 天前
你要是担心数据库 group by 构造月份比较慢,我倒是觉得你可以试试 select (里面放 12 个 select)😁
但我往往选择相信数据库(
luoyou1014
134 天前
如果是 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
tlerbao
134 天前
@luoyou1014 可惜还是 5.7
luoyou1014
129 天前

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1004308

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX