V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tlerbao
V2EX  ›  程序员

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

  •  
  •   tlerbao · 120 天前 · 1725 次点击
    这是一个创建于 120 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面的代码上线后会不会崩 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);
    
    14 条回复    2024-01-03 14:49:27 +08:00
    Belmode
        1
    Belmode  
       120 天前
    不懂 php ,这么写,在数据量尚可的情况下肯定没有业务问题,只是看起来不够凝炼。
    从开发惯性上来说,还是 group by 更合理一点。
    yc8332
        2
    yc8332  
       120 天前
    那肯定不至于。就是慢点而已。
    tlerbao
        3
    tlerbao  
    OP
       120 天前
    @yc8332 如果是您您会怎么写?
    tlerbao
        4
    tlerbao  
    OP
       120 天前
    @Belmode 听说 group by 也很影响效率
    TiaoYeTaiLang
        5
    TiaoYeTaiLang  
       120 天前
    一次性查 1 年的数据,和查 12 次 1 个月的数据,你觉得哪个对于数据库来说哪种方式是压力最分散的
    5200
        6
    5200  
       120 天前
    一般不要在循环里面写 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
        7
    Rache1  
       120 天前
    你这 status 这里的完全可以用 where in ... group by 。

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

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


    另外就是,对于这种需求,如果访问比较频繁的话,最好的做法你自己也提到了,就是单独拿一张表来计数,或者在现有的基础上配合上缓存。
    tlerbao
        8
    tlerbao  
    OP
       120 天前
    @Rache1 没听太明白呢,愿闻其详小哥
    Rache1
        9
    Rache1  
       120 天前
    @tlerbao #8 6 楼已经有代码了
    JackSlowFcck
        10
    JackSlowFcck  
       120 天前
    上线后的代码稳定性要看服务器和数据库,但用 GROUP BY 和加索引、缓存等方法,能让查询更高效,系统负担更小。
    iseki
        11
    iseki  
       120 天前
    你要是担心数据库 group by 构造月份比较慢,我倒是觉得你可以试试 select (里面放 12 个 select)😁
    但我往往选择相信数据库(
    luoyou1014
        12
    luoyou1014  
       120 天前
    如果是 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
        13
    tlerbao  
    OP
       120 天前
    @luoyou1014 可惜还是 5.7
    luoyou1014
        14
    luoyou1014  
       115 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   873 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 21:53 · PVG 05:53 · LAX 14:53 · JFK 17:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.