有效地将查询转换为预期的数组 - Laravel

Posted

技术标签:

【中文标题】有效地将查询转换为预期的数组 - Laravel【英文标题】:Convert queries to expected array efficiently - Laravel 【发布时间】:2021-04-10 20:13:31 【问题描述】:

我有一个dictionaries 表,如下所示:

这是我想要的数组结果:

我已经通过这些丑陋的代码实现了结果:

    $dictionaries = Dictionary::all();
    $carriers_array = [];
    $carriers = $dictionaries->unique('Carrier');
    foreach($carriers as $carrier) 
        $carriers_array[] = $carrier->Carrier;
    

    $DOM_INLs_array = [];
    foreach($carriers_array as $carrier_item) 
        $DOM_INLs = $dictionaries->where('Carrier', $carrier_item)->unique('DOM_INL');
        foreach($DOM_INLs as $DOM_INL) 
            $DOM_INLs_array[$carrier_item][] = $DOM_INL->DOM_INL;
        
        
    

    $groups_array = [];
    foreach($DOM_INLs_array as $carrier => $DOM_INLs) 
        foreach($DOM_INLs as $DOM_INL) 
            $groups = $dictionaries->where('Carrier', $carrier)->where('DOM_INL', $DOM_INL)->unique('Group');
            foreach($groups as $group) 
                $groups_array[$carrier][$DOM_INL][] = $group->Group;
            
        
    

    $routes_array = [];
    foreach($groups_array as $carrier => $DOM_INLs) 
        foreach($DOM_INLs as $DOM_INL => $groups) 
            foreach($groups as $group) 
                $routes = $dictionaries->where('Carrier', $carrier)->where('DOM_INL', $DOM_INL)->where('Group', $group)->unique('Route');
                foreach($routes as $route) 
                    $routes_array[$carrier][$DOM_INL][$group][] = $route->Route;
                
            
        
    

    $sectors_array = [];
    foreach($routes_array as $carrier => $DOM_INLs) 
        foreach($DOM_INLs as $DOM_INL => $groups) 
            foreach($groups as $group => $routes) 
                foreach($routes as $route) 
                    $sectors = $dictionaries->where('Carrier', $carrier)->where('DOM_INL', $DOM_INL)->where('Group', $group)->where('Route', $route)->unique('Sector');
                    foreach($sectors as $sector) 
                        $sectors_array[$carrier][$DOM_INL][$group][$route][] = $sector->Sector;
                    
                
            
        
    

    dd($sectors_array);

但是它运行得很慢,我想要另一种方法来获得相同的结果但更有效。有人可以帮忙吗?

【问题讨论】:

请编辑您的问题并包括您的查询。 @AhmadKarimi 我更新了包含$dictionaries查询的问题 【参考方案1】:

这看起来像是一堆嵌套的 maps 和 groupBys,最后是 pluck

箭头函数,php 7.4+:

$dictionaries->groupBy('Carrier')
    ->map(fn ($i) => $i->groupBy('DOM_INL')
        ->map(fn ($i) => $i->groupBy('Group')
            ->map(fn ($i) => $i->groupBy('Route')
                ->map->pluck('Sector')
            )
        )
    );

使用匿名函数:

$dictionaries->groupBy('Carrier')->map(function ($i) 
    return $i->groupBy('DOM_INL')->map(function ($i) 
        return $i->groupBy('Group')->map(function ($i) 
            return $i->groupBy('Route')->map->pluck('Sector');
        );
    );
);

如果您只需要以这种方式分组的这些结果并且不需要叶子只是“部门”值,这将是 1 次调用 groupBy

$dictionary->groupBy(['Carrier', 'DOM_INL', 'Group', 'Route'])

【讨论】:

您的解决方案看起来很有希望,但是这些代码看起来像是新版本的php,能否给我与旧php版本兼容的代码? 当然,检查更新,看看是否适合你 我刚刚遇到了另一个问题。也就是说,要获取当前结果,我必须查询整个表并将所有结果加载到内存中。如果表只有 10,000 行,我不会有问题。但是,如果表有 10 万行、20 万行或更多……每个查询将占用 1GB 或更多的内存,导致服务器死亡。我用的VPS只有2GB内存……你有办法帮我解决内存使用问题,还能得到和现在一样的结果吗?

以上是关于有效地将查询转换为预期的数组 - Laravel的主要内容,如果未能解决你的问题,请参考以下文章

有效地将不均匀的列表列表转换为用 nan 填充的最小包含数组

在 C# 中有效地将字符串转换为字节数组(不使用编码)[重复]

在 SQL Server 视图中有效地将行转换为列

有效地将 16 位 short 转换为 8 位 char

在R中有效地将反斜杠转换为正斜杠

如何使用缩放有效地将 16 位无符号短转换为 8 位无符号字符?