Laravel Eloquent按天分组结果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel Eloquent按天分组结果相关的知识,希望对你有一定的参考价值。

我目前有一个page_views表,每次访问者访问一个页面时记录一行,记录用户的ip / id和页面本身的id。我应该补充一点,created_at列的类型为:timestamp,因此它包含小时/分钟/秒。当我尝试groupBy查询时,由于秒差异,它不会将相同的日期组合在一起。

created_at         page_id       user_id
==========         =======       =======
10-11-2013            3            1
10-12 2013            5            5
10-13 2013            5            2
10-13 2013            3            4
  ...                ...          ...

我想根据观点/日得到结果,所以我可以得到类似的结果:

  date          views
  ====          =====
10-11-2013       15
10-12 2013       45
  ...            ...

我想我需要深入研究DB :: raw()查询来实现这一目标,但任何见解都会有很大帮助,谢谢

编辑:添加了created_at格式的说明。

答案

我相信我找到了一个解决方案,关键是mysql中的DATE()函数,它将DateTime转换为日期:

DB::table('page_views')
      ->select(DB::raw('DATE(created_at) as date'), DB::raw('count(*) as views'))
      ->groupBy('date')
      ->get();

但是,这并不是一个真正的Laravel Eloquent解决方案,因为这是一个原始查询。以下是我在Eloquent-ish语法中提出的。第一个where子句使用碳日期进行比较。

$visitorTraffic = PageView::where('created_at', '>=', CarbonCarbon::now->subMonth())
                            ->groupBy('date')
                            ->orderBy('date', 'DESC')
                            ->get(array(
                                DB::raw('Date(created_at) as date'),
                                DB::raw('COUNT(*) as "views"')
                            ));
另一答案

在mysql中,您可以添加MONTH关键字,将时间戳作为laravel中的参数,您可以这样做

Payement::groupBy(DB::raw('MONTH(created_at)'))->get();
另一答案

我建立了一个用于统计的laravel包:https://github.com/Ifnot/statistics

它基于雄辩,碳和指标,所以它非常容易使用。它可能对提取日期分组指标很有用。

$statistics = Statistics::of(MyModel::query());

$statistics->date('validated_at');

$statistics->interval(Interval::$DAILY, Carbon::createFromFormat('Y-m-d', '2016-01-01'), Carbon::now())

$statistics->indicator('total', function($row) {
    return $row->counter;
});

$data = $statistics->make();

echo $data['2016-01-01']->total;

```

另一答案

我知道这是一个老问题,有多个答案。根据文档和我在laravel上的经验,如何处理事物的良好“雄辩方式”

在你的模型中,像这样添加一个mutator / Getter

public function getCreatedAtTimeAttribute()
{
   return $this->created_at->toDateString();
}

另一种方法是在模型中转换列,填充$cast数组

$casts = [
   'created_at' => 'string'
]

这里的问题是你不能再在这个模型上使用Carbon,因为Eloquent总是将列转换为字符串

希望能帮助到你 :)

另一答案

您还可以通过以下方式解决此问题:

$totalView =  View::select(DB::raw('Date(read_at) as date'), DB::raw('count(*) as Views'))
        ->groupBy(DB::raw('Date(read_at)'))
        ->orderBy(DB::raw('Date(read_at)'))
        ->get();
另一答案

你可以使用Carbon(集成在Laravel中)

// Carbon
use CarbonCarbon;   
$visitorTraffic = PageView::select('id', 'title', 'created_at')
    ->get()
    ->groupBy(function($date) {
        return Carbon::parse($date->created_at)->format('Y'); // grouping by years
        //return Carbon::parse($date->created_at)->format('m'); // grouping by months
    });
另一答案

我就是这样做的。一个简短的例子,但使我的查询更易于管理

$visitorTraffic = PageView::where('created_at', '>=', CarbonCarbon::now->subMonth())
                        ->groupBy(DB::raw('Date(created_at)'))
                        ->orderBy('created_at', 'DESC')->get();
另一答案

我有同样的问题,我现在正在使用Laravel 5.3。

我用DATE_FORMAT()

->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))

希望这会对你有所帮助。

另一答案

您可以使用mysql(See here for Mysql/Mariadb help)根据格式化日期过滤结果,并在laravel-5.4中使用类似的内容:

Model::selectRaw("COUNT(*) views, DATE_FORMAT(created_at, '%Y %m %e') date")->groupBy('date')->get();
另一答案

像大多数数据库问题一样,它们应该通过使用数据库来解决。

存储要分组的数据并使用索引可以实现一种有效且清晰的方法来解决此问题。

Create the migration

    $table->tinyInteger('activity_year')->unsigned()->index();
    $table->smallInteger('activity_day_of_year')->unsigned()->index();

Update the Model

<?php

namespace AppModels;

  use DB;
  use CarbonCarbon;
  use IlluminateDatabaseEloquentModel;

  class PageView extends Model
  {
  public function scopePerDay($query){

     $query->groupBy('activity_year');
     $query->groupBy('activity_day_of_year');

     return $query;

  }

  public function setUpdatedAt($value)
  {   
    $date = Carbon::now();

    $this->activity_year = (int)$date->format('y');
    $this->activity_day_of_year = $date->dayOfYear;

    return parent::setUpdatedAt($value);
 }

Usage

   $viewsPerDay = PageView::perDay()->get();
另一答案

要根据DATE而不是DATETIME对数据进行分组,可以使用CAST功能。

$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(DB::raw('CAST(created_at AS DATE)'));
另一答案

警告:未经测试的代码。

$dailyData = DB::table('page_views')
    ->select('created_at', DB::raw('count(*) as views'))
    ->groupBy('created_at')
    ->get();
另一答案

使用不含碳的Laravel 4.2

这是我抓住最近十天的方法,并计算每天create_at时间戳的每一行。

$q = Spins::orderBy('created_at', 'desc')
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
->take(10)
->get(array(
      DB::raw('Date(created_at) as date'),
      DB::raw('COUNT(*) as "views"')
  ));


foreach ($q as $day) {

  echo $day->date. " Views: " . $day->views.'<br>';

}

希望这可以帮助

以上是关于Laravel Eloquent按天分组结果的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel 查询数据并按天分组

Laravel 多订单按天分组查看

Eloquent - 按月、年和分页分组

Laravel Eloquent,按月/年分组

按 id 分组 Laravel Eloquent 枢轴值

Laravel Eloquent 查询,带有连接、计数和分组依据