如何避免 laravel(php) 中的嵌套查询?

Posted

技术标签:

【中文标题】如何避免 laravel(php) 中的嵌套查询?【英文标题】:How can i avoid nested queries in laravel(php)? 【发布时间】:2018-09-27 11:20:52 【问题描述】:

我在这里有两张桌子。我想使用优化的代码从这些表中检索数据。

表格:

game_sessions
Id, SessionName, StartTime

games
Id, GamesSessionId, GameName

代码 A:

$sessions = DB :: select('select Id as sessionId, SessionName from game_sessions');
foreach($sessions as $session)

    $games = DB :: select('select Id as GameId, GameName from games where games.GameSessionId = '.$session->sessionId);  
    $session->Games = array();
    $session->Games = $games;

return array('status'=>true, 'session'=>$sessions);

输出:($sessions)


    "status": true,
    "session": 
    [
        
            "sessionId": 1,
            "SessionName": "Regular bingo Manual",
            "Games": [
                
                    "GameId": 1,
                    "GameName": "Game1"
                
            ]
        ,
        
            "sessionId": 2,
            "SessionName": "Regular Automatic",
            "Games": [
                
                    "GameId": 2,
                    "GameName": "Game2"
                ,
                
                    "GameId": 3,
                    "GameName": "Game1"
                
            ]
        ,
        
            "sessionId": 3,
            "SessionName": "RegularDoubleAction",
            "Games": [
                
                    "GameId": 4,
                    "GameName": "Game1"
                
            ]
        
    ]

代码 B:

$sessions = DB :: select('select game_sessions.Id as sessionId, SessionName, games.Id as GameId, games.GameName from game_sessions
            join games on games.GameSessionId = game_sessions.Id');
return array('status'=>true, 'session'=>$sessions);

输出:($sessions)


    "status": true,
    "session": 
    [
        
            "sessionId": 1,
            "SessionName": "Regular bingo Manual",
            "GameId": 1,
            "GameName": "Game1"
        ,
        
            "sessionId": 2,
            "SessionName": "Regular Automatic",
            "GameId": 2,
            "GameName": "Game2"
        ,
        
            "sessionId": 2,
            "SessionName": "Regular Automatic",
            "GameId": 3,
            "GameName": "Game1"
        ,
        
            "sessionId": 3,
            "SessionName": "RegularDoubleAction",
            "GameId": 4,
            "GameName": "Game1"
        
    ]

这里我使用两种类型的代码。 在代码 A 中,我使用嵌套查询,但我会得到按会话分组的输出。 在代码 B 中,我没有使用嵌套查询(通过使用连接避免嵌套查询),但我没有得到按会话分组的输出。

我需要的是我不想使用嵌套查询,但我希望我的输出按会话分组。 我怎样才能做到这一点?

【问题讨论】:

“我想使用优化的代码来检索数据” - 所以我猜这段代码确实有效,你只是想知道是否有更好的方法?那你应该把它发到Code Review。 好的。对不起。我从来不知道代码审查。下次我会用那个。谢谢。 【参考方案1】:

您需要创建具有关系的模型

https://laravel.com/docs/5.6/eloquent

https://laravel.com/docs/5.6/eloquent-relationships

创建具有以下关系的GameSession 模型:

function games() 
    return $this->hasMany(Game::class, 'GamesSessionId', 'Id');

Game 模型上创建逆关系:

function session () 
    return $this->belongsTo(GameSession::class)

这将允许您获得GameSession 及其Games

第一种方式是预加载

https://laravel.com/docs/5.6/eloquent-relationships#eager-loading

$gameSessionWithGames = GameSession::with('games')->find($gameSessionId);

这将为您提供 GameSession 及其所有 Games 作为集合的属性

或者直接通过关系:

$gamesForSession = GameSession::find(gameSessionId)->games;

这将返回属于GameSession的所有Games

--

以上都将返回一个集合,然后你可以map

https://laravel.com/docs/5.6/collections#method-map

只得到你需要的结果

或者通过将->select('...', '..', '.') 添加到您的查询构建器

https://laravel.com/docs/5.6/queries#selects

【讨论】:

@H H 方法非常好。我得到了我想要的。 :)

以上是关于如何避免 laravel(php) 中的嵌套查询?的主要内容,如果未能解决你的问题,请参考以下文章

Django Serializer 嵌套创建:如何避免对关系的 N+1 查询

Laravel 5.5 检索嵌套关系中的第一条记录

如何使用 Laravel 查询构建器编写嵌套连接?

如何使用 Laravel 5.6 在 Laravel Eloquent 中实现嵌套 MySQL 查询

如何使用 Laravel 的查询构建器执行嵌套连接?

刀片模板中的多对多关系中的 Laravel 嵌套查询