有一个名为requests的表,其中一列名为status,我可以通过 HasManyThrough 关系访问此表。
表格如下:
id | status | request
--------------------------
1 | 1 | lorem ipsum
2 | 2 | lorem ipsum
3 | 1 | lorem ipsum
4 | 3 | lorem ipsum
5 | 1 | lorem ipsum
我需要以有效的方式计算所有不同的状态行,我正在寻找的结果是这样的:
status | status_count
---------------------
1 | 3
2 | 1
3 | 1
此外,我需要能够做到这样的事情:
$status[1] Or $status->id[1] // which prints out the count of that status
我知道这两个选项都很难看:
1。使用过滤器:
// Through a table named group which contains year column
$requests = Auth::user()->requests()->where('year', 2016)->get();
$status[1] = $requests->filter(
function($request){
return $request->status == 1;
})->count();
现在我有10个状态ID,我应该重复这个代码10次,如果我有100个状态...那么这不是一个好的选择。
2。试图创建一个正确的SQL:
据我所知,执行此操作的正确SQL语句如下所示:
SELECT 'status', COUNT(*) FROM requests GROUP BY status
为了创建这个声明,我正在这样做:
$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016])
->lists('id');
$requests = DB::table('requests')
->select( DB::raw('count(status) as status_count, status') )
->whereIn('group_id', $groups)
->groupBy('status')
->get();
这是我的dd输出:
array:2 [▼
0 => {
+"status_count": "3"
+"status": "1"
}
1 => {
+"status_count": "1"
+"status": "2"
}
2 => {
+"status_count": "1"
+"status": "3"
}
]
我不知道如何使用它们,例如我怎么知道状态2的数量是多少?我可以使用foreach创建一个状态为键的数组,并将status_counts作为值,但我正在寻找正确的方法来执行此操作。
另一件事是如何通过eloquent而不是DB来创建这个SQL语句? 还有其他方法我错过了吗?
答案 0 :(得分:3)
好的,这就是我所做的:
首先,我设法创造了一个正确的SQL,只有雄辩和得到 状态和他们的计数只有1个请求。
这是hasManyThrough关系:
public function requests()
{
return $this->hasManyThrough('App\Models\Request',
'App\Models\Group', 'owner_id', 'group_id');
}
然后获取所需请求状态的计数:
$requests = Auth::user()->requests()->
select( DB::raw('count(requests.status) as count, requests.status') )->
groupBy('requests.status')->where('year', '2016')->get();
我们的结果再次完全符合我们的要求:
status | status_count
---------------------
1 | 3
2 | 1
3 | 1
这次我们有两种方法可以处理计数,我首先使用新方法:
<强> 1。使用:
// returns null if there is no row with status of 1
$status = $projects->where('status_id', "1")->first();
// if $status is null there is no row with status of 1 so return 0
echo ( empty($status) ) ? 0 : $status->count;
容易对吗?但它并不像我们想要的那么干净。
<强> 2。 foreach技巧:
正如我在我的问题中提到的,我们可以使用foreach来创建一系列状态及其计数。但是当我们尝试获取查询结果中不存在的状态计数时会发生什么?我们将收到一个错误:未定义的偏移量。
这是我的想法:
首先,我们将创建一个数组来保存所有状态代码及其数量 用零填充此数组。
我的系统只有10个状态码,所以:
$requests_counts = array_fill(1, 10, 0); // status 1 to 10 - default count: 0
然后使用foreach语句,我们只覆盖在查询结果中有计数的索引:
foreach($requests as $request)
$requests_counts[$request->status] = $request->count;
所以所有状态代码都会有一个值,即使是那些不存在的值 我们的查询结果。
*所有状态代码的计数
但是,如果我们想要打印出所有请求的数量,无论它们具有什么状态代码,该怎么办?我们应该创建一个其他查询并计算所有结果行吗?不,我们将使用名为array_sum的函数:
array_sum($requests_counts); // prints out number of all requests
答案 1 :(得分:1)
$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016])
->groupBy('status')
->select( DB::raw('status , COUNT(*) as status_count') )
->get();
答案 2 :(得分:0)
我会坚持你的第二个选择,只需要一点点调整。
$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016])
->lists('id');
$requests = DB::table('requests')
->select( DB::raw('count(status) as status_count, status') )
->whereIn('group_id', $groups)
->groupBy('status')
->get();
$output = [];
foreach ($requests as $a)
{
$output[$a->status] = $a->status_count;
}
然后在您的输出中,$output[1]
计入状态1等...