
本教程详细介绍了如何使用 laravel query builder 实现复杂的数据库查询,包括多表联接、数据聚合(sum、round)、分组(group by)以及基于聚合结果的条件筛选(having)。文章将通过一个具体的案例,指导开发者如何将原始sql语句转换为query builder代码,并解决在数据传递至视图时可能出现的“undefined variable”错误,确保数据能够正确获取并在blade模板中展示。
在构建复杂的Laravel Query Builder查询之前,首先理解原始SQL语句的功能至关重要。以下是需要转换的原始SQL查询,它涉及多个表的联接、数据聚合和复杂的筛选条件:
SELECT ru.external_ref_no AS SID, usd.user_name AS Username, rs.servicecode AS Package, rc.clientdesc as Entity, rc.clientip as NAS_IP, ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) AS Upload, ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Download, ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) + ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Total_Usage FROM user_session_detail usd, radservice rs, radclient rc, radgroup rg, raduser ru WHERE ru.username=usd.user_name AND rs.serviceid=usd.service_id AND rg.groupid=usd.group_id AND usd.client_id=rc.clientid AND usd.SESSION_START_TIME > '2021-09-30 00.00.01' AND usd.SESSION_START_TIME < '2021-09-30 23.59.59' GROUP BY usd.user_name HAVING (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 > 15 AND (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 < 20;
该SQL查询的核心功能包括:
将上述复杂的SQL语句转换为Laravel Query Builder代码时,需要注意联接顺序、select 语句的构造以及 having 子句的使用。
在将原始SQL转换为Query Builder时,开发者可能会遇到一些问题,例如:
以下是原始问题中提供的初始Laravel Query Builder代码,其中包含了一些需要修正的地方:
public function nsuresecret(){
$user_session_detail = DB::table('user_session_detail')
->select(array('user_session_detail.*'), DB::raw('raduser.external_ref_no AS SID, user_session_detail.user_name AS Username, radservice.servicecode AS Package,
radclient.clientdesc as Entity, radclient.clientip as NAS_IP,
ROUND((ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) AS Upload,
ROUND((ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Download,
ROUND((ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) + ROUND((ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Total_Usage'))
->join('radservice', 'user_session_detai.service_id', '=', 'radservice.serviceid') // 注意这里的拼写错误
->join('radclient', 'user_session_detail.client_id', '=', 'radclient.clientid')
->join('radgroup', 'user_session_detail.group_id', '=', 'radgroup.groupid')
->join('raduser', 'user_session_detail.user_name', '=', 'raduser.username')
->whereBetween('user_session_detail.SESSION_START_TIME', ['2021-09-30 00.00.01', '2021-09-30 23.59.59'])
->groupBy('user_session_detail.user_name')
->havingRaw((ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 > 15
AND (ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 < 20)
->get();
return view('reports.secretuserlist',compact('user_session_detail'));
}为了正确实现原始SQL的功能并避免潜在错误,我们可以按照以下方式优化Query Builder代码。主要修正包括:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; // 引入DB门面
class ReportController extends Controller // 假设你的控制器名为ReportController
{
public function nsuresecret()
{
$user_session_detail = DB::table('user_session_detail')
// 执行多表联接操作
->join('radservice', 'user_session_detail.service_id', '=', 'radservice.serviceid')
->join('radclient', 'user_session_detail.client_id', '=', 'radclient.clientid')
->join('radgroup', 'user_session_detail.group_id', '=', 'radgroup.groupid')
->join('raduser', 'user_session_detail.user_name', '=', 'raduser.username')
// 筛选时间范围
->whereBetween('user_session_detail.SESSION_START_TIME', ['2021-09-30 00:00:01', '2021-09-30 23:59:59'])
// 按用户名分组
->groupBy('user_session_detail.user_name')
// 选择需要的列,包括通过DB::raw实现的复杂聚合计算
->select(
'user_session_detail.*', // 如果需要user_session_detail表的所有原始列,可以包含此行
// 注意:原始SQL只选择了特定别名列,如果不需要所有原始列,可以移除此行
DB::raw('raduser.external_ref_no AS SID'),
DB::raw('user_session_detail.user_name AS Username'),
DB::raw('radservice.servicecode AS Package'),
DB::raw('radclient.clientdesc as Entity'),
DB::raw('radclient.clientip as NAS_IP'),
DB::raw('ROUND((ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) AS Upload'),
DB::raw('ROUND((ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Download'),
DB::raw('ROUND((ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) + ROUND((ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Total_Usage')
)
// 对聚合结果进行筛选
->havingRaw('(ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 > 15 AND (ROUND((SUM(user_session_detail.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(user_session_detail.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 < 20')
// 执行查询并获取结果集
->get();
// 将查询结果传递给视图
return view('reports.secretuserlist', compact('user_session_detail'));
}
}注意事项:
在控制器中获取到数据后,需要将其传递给Blade视图进行展示。compact('user_session_detail') 方法会将 $user_session_detail 变量以同名键值对的形式传递给视图。
在视图文件 resources/views/reports/secretuserlist.blade.php 中,可以使用 @foreach 循环遍历 $user_session_detail 集合,并访问每个对象的属性来展示数据。
<table class="table table table-bordered table-striped table-hover">
<thead>
<tr>
<th>SID</th>
<th>Username</th>
<th>Package</th>
<th>Entity</th>
<th>NAS_IP</th>
<th>Upload (GB)</th>
<th>Download (GB)</th>
<th>Total Usage (GB)</th>
</tr>
</thead>
<tbody>
@foreach($user_session_detail as $usd)
<tr>
<td>{{ $usd->SID }}</td>
<td>{{ $usd->Username }}</td>
<td>{{ $usd->Package }}</td>
<td>{{ $usd->Entity }}</td>
<td>{{ $usd->NAS_IP }}</td>
<td>{{ $usd->Upload }}</td>
<td>{{ $usd->Download }}</td>
<td>{{ $usd->Total_Usage }}</td>
</tr>
@endforeach
</tbody>
</table>
@if($user_session_detail->isEmpty())
<p>没有找到符合条件的用户会话详情。</p>
@endif注意事项:
以上就是Laravel Query Builder 多表联接、聚合与复杂条件查询指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号