Laravel Eloquent按天分组结果

jct*_*jct 38 php mysql sql laravel laravel-4

我目前有一个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
  ...                ...          ...
Run Code Online (Sandbox Code Playgroud)

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

  date          views
  ====          =====
10-11-2013       15
10-12 2013       45
  ...            ...
Run Code Online (Sandbox Code Playgroud)

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

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

jct*_*jct 48

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

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

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

$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
                            ->groupBy('date')
                            ->orderBy('date', 'DESC')
                            ->get(array(
                                DB::raw('Date(created_at) as date'),
                                DB::raw('COUNT(*) as "views"')
                            ));
Run Code Online (Sandbox Code Playgroud)


ded*_*ede 45

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

// Carbon
use Carbon\Carbon;   
$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
    });
Run Code Online (Sandbox Code Playgroud)

  • 但是这会在运行查询后对它进行分组,这意味着它在php中进行处理,这要慢得多. (23认同)
  • PHP中的处理并不总是较慢,但这完全取决于您的应用程序的要求.这是一种方法. (4认同)

Qui*_*ins 20

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

$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
                        ->groupBy(DB::raw('Date(created_at)'))
                        ->orderBy('created_at', 'DESC')->get();
Run Code Online (Sandbox Code Playgroud)


ako*_*ako 8

您可以使用 mysql 根据格式化日期过滤结果(请参阅此处获取 Mysql/Mariadb 帮助)并在 laravel-5.4 中使用类似的内容:

Model::selectRaw("COUNT(*) views, DATE_FORMAT(created_at, '%Y %m %e') date")
    ->groupBy('date')
    ->get();
Run Code Online (Sandbox Code Playgroud)


小智 6

我有同样的问题,我目前使用的是 Laravel 5.3。

我用 DATE_FORMAT()

->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
Run Code Online (Sandbox Code Playgroud)

希望这会帮助你。


小智 6

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

存储你想要分组的数据并使用索引,你可以实现一种高效而清晰的方法来解决这个问题。

创建迁移

    $table->tinyInteger('activity_year')->unsigned()->index();
    $table->smallInteger('activity_day_of_year')->unsigned()->index();
Run Code Online (Sandbox Code Playgroud)

更新模型

<?php

namespace App\Models;

  use DB;
  use Carbon\Carbon;
  use Illuminate\Database\Eloquent\Model;

  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);
 }
Run Code Online (Sandbox Code Playgroud)

用法

   $viewsPerDay = PageView::perDay()->get();
Run Code Online (Sandbox Code Playgroud)


Sha*_*ngh 5

PageView::select('id','title', DB::raw('DATE(created_at) as date'))
          ->get()
          ->groupBy('date');
Run Code Online (Sandbox Code Playgroud)


J.T*_*mes 1

警告:未经测试的代码。

$dailyData = DB::table('page_views')
    ->select('created_at', DB::raw('count(*) as views'))
    ->groupBy('created_at')
    ->get();
Run Code Online (Sandbox Code Playgroud)