从Eloquent查询计数

时间:2018-03-19 12:54:30

标签: mysql laravel count laravel-5.6

我在eloquent中有一个查询正确计算计数,因为它应该在这里:

$query = A::withCount(
        ['bs' =>
            function ($query) use ($from, $to) {
                $query->where(function ($query) use ($from) {
                    $query->whereDate('start', '<', $from)
                        ->whereDate('end', '>', $from);
                })->orWhere(function ($query) use ($to) {
                    $query->whereDate('start', '<', $to)
                        ->whereDate('end', '>', $to);
                })->orWhere(function ($query) use ($from, $to) {
                    $query->whereDate('start', '>', $from)
                        ->whereDate('end', '<', $to);
                });
        }])
        ->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
        ->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
        ->where('cmp3', '<=', $request->cmp3)
        ->where('cmp4', '<=', $request->cmp4)
        ->with('more_relations');

    return AResource::collection($query->paginate(5));

这是一个API控制器。我用这个用于Vue的前端分页。我想使用count来过滤掉Abs_count的所有bs_count,但链接一个where子句不起作用,因为它是一个聚合,并且它返回一个错误,因为它没有找到一个名为having的列。我发现,解决方案是使用bs_count子句。我找到了这段代码,但是当我尝试转换它时,它不起作用,返回相同的错误,没有找到名为DB::table('bs') ->select('*', DB::raw('COUNT(*) as bs_count')) ->groupBy('a_id') ->having('bs_count', '=' , 0); 的列。

having

这是没有在计数上添加额外的查询,因为我想尝试这个以查看它是否先工作,但它没有。

DB::table()子句是正确的方法吗?我认为我需要使用Eloquent而不是where bs_count = 0语法,因为资源构建器使用模型结构来构建资源响应。

总之,我正在尝试使用我在第一个查询中计算的计数,并对其进行查询:library(tibble) library(dplyr) library(lubridate) tbl <- tribble( ~TIME, ~MEASURE, "2018-01-01 06:58:50", 05, "2018-01-01 07:00:00", 10, "2018-01-01 07:04:45", 20, "2018-01-01 07:04:55", 25, "2018-01-01 07:21:00", 20, "2018-01-01 07:58:04", 18, "2018-01-01 07:59:59", 12, "2018-01-01 08:00:00", 17, "2018-01-01 08:01:04", 30 ) %>% mutate(TIME = ymd_hms(TIME)) 。有没有办法在Laravel中执行此操作并仍然能够将结果传递给API资源?

2 个答案:

答案 0 :(得分:0)

使用HAVING子句是正确的方法。

问题在于Laravel分页本身并不支持HAVING条款。
您必须手动创建pagniator:
How to use paginate() with a having() clause when column does not exist in table

使用DB的测试查询无效,因为在分组时无法选择所有列:

->select('a_id', DB::raw('COUNT(*) as bs_count'))

答案 1 :(得分:0)

正如我发现的那样,Laravel确实有一个内置的解决方案。 From the docs,我找到了函数whereHas()whereDoesntHave()。这些函数允许您传递一个闭包,根据它在幕后的计数来过滤行。我如何调整我以前的解决方案是:

$query = A::whereDoesntHave(
    'bs', 
        function ($query) use ($from, $to) {
            $query->where(function ($query) use ($from) {
                $query->whereDate('start', '<', $from)
                    ->whereDate('end', '>', $from);
            })->orWhere(function ($query) use ($to) {
                $query->whereDate('start', '<', $to)
                    ->whereDate('end', '>', $to);
            })->orWhere(function ($query) use ($from, $to) {
                $query->whereDate('start', '>', $from)
                    ->whereDate('end', '<', $to);
            });
    )
    ->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
    ->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
    ->where('cmp3', '<=', $request->cmp3)
    ->where('cmp4', '<=', $request->cmp4)
    ->with('more_relations');

return AResource::collection($query->paginate(5));

这会根据传递的查询自动计算B,并且只返回计数为零的行,这正是我需要的。