【问题标题】:Combine two queries into one in Laravel Query Builder or SQL在 Laravel Query Builder 或 SQL 中将两个查询合二为一
【发布时间】:2018-08-25 23:17:49
【问题描述】:

SQL 查询不是我的强项之一,我遇到了一个我能够解决但希望改进并提高效率的问题。我在这些示例中使用了 Laravel 的查询生成器,但如果必须,我不介意使用原始请求。

目前我正在做如下两个查询并在之后合并它们。

 $acc_id = 10;
 $locat_id= 3;  

//First get all sites with account id
$allSites = collect(DB::table('sites')->where('acc_id', $acc_id)->get()):

//Next get only sites with account id and connections with current location id
$connectedSites = collect( 
    DB::table('sites')
        ->select('sites.id','name','active','url')
        ->join('connections as conn','sites.id','=','conn.site_id')
        ->where('acc_id',$acc_id)
        ->where('conn.locat_id',$locat_id)
        ->get()
);

//Merge the collections and drop first row with duplicate site_id
$sites = $allSites->merge($connectedSites)->keyBy('id');

return $sites;

所以这给了我想要的结果。例如。与帐户 ID 关联的所有站点,以及与帐户 ID 和位置 ID 关联的站点的连接数据。 但是,如果可能的话,我想学习如何在一个查询中执行此操作。

【问题讨论】:

  • 每个站点是否至少有一个连接?
  • 没有,有些网站没有连接。它们(站点)在创建帐户时默认添加。连接由用户稍后进行。
  • 也许问题的一部分可能是我对表关系的工作方式设计不佳。在这一点上,它可以按照我的需要完美运行,但我喜欢尽可能地改进。

标签: php sql laravel laravel-5


【解决方案1】:

尝试左连接:

$sites = DB::table('sites')
    ->select('sites.*','name','active','url')
    ->leftJoin('connections as conn', function($query) use($locat_id) {
        $query->on('sites.id', '=', 'conn.site_id')
            ->where('conn.locat_id', $locat_id);
    })
    ->where('acc_id',$acc_id)
    ->get();

【讨论】:

  • 左连接仍然没有返回所有带有 $acc_id 的记录。只有那些同时拥有 $acc_id 和 $locat_id 的人。
  • 实际上我认为这确实有效。但是 $locat_id 超出范围或其他东西,似乎没有传递到函数中。如果我像 ->where('conn.locate_id, 3)` 那样硬编码它就可以了,但如果我这样做 ->where('conn.locate_id, $locat_id)` 就不行了
  • 抱歉,我的答案已修正。
  • 我第一次查看您的修复时错过了use 声明。 :) 这太棒了。我不知道您可以在这样的查询中使用函数。这似乎产生了与我对两个查询解决方案所做的相同的结果。谢谢一百万!
  • 知道我可以去哪里阅读以提高我对那里发生的事情的理解吗?
【解决方案2】:

这可以通过一个查询来完成,但我使用 eloquent 而不是查询生成器。查看 with() 方法,它允许您预先加载关系。

$sites = Sites::with('connections')->where('acc_id', $acc_id)->get();

现在您可以从模型实例访问连接数据,而无需进行任何查询。

foreach($sites as $site){
    $site->connection->stuff; // No query generated
}

如果您需要将两者分开,这也很容易。

$connectedSites = $sites->where('connection.locat_id', $locat_id)
// No query generated from the above, but now $connectedSites has all of
// the connected sites

当您进入 laravel 的集合时,您会发现使用它们可以替换很多查询。

https://laravel.com/docs/5.6/collections#available-methods

【讨论】:

  • 谢谢。我经常将 Eloquent 用于单个查询,并且非常喜欢集合和 laravel 提供的所有用于处理它们的方法。您的建议可能确实有效,但我的真正目标是学习如何用更像 SQL 的方式构建查询。
  • 啊,我明白了。可悲的是,我在 eloquent 方面比在 SQL 方面要好得多。希望你能找到答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多