计算每个状态的行 - Laravel雄辩

时间:2016-07-01 10:58:01

标签: php laravel eloquent

有一个名为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语句? 还有其他方法我错过了吗?

3 个答案:

答案 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等...