web-dev-qa-db-ja.com

Laravel日ごとにグループ化された雄弁な結果を取得

現在、訪問者がページにアクセスするたびに1行を記録し、ユーザーのIP/IDとページ自体のIDを記録するpage_viewsのテーブルがあります。 created_at列のタイプはタイムスタンプであるため、時間/分/秒が含まれることを追加する必要があります。 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
  ...                ...          ...

1日あたりの再生回数に基づいて結果を取得したいので、次のような結果を得ることができます。

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

私はこれを達成するためにDB :: raw()クエリを掘り下げる必要があると考えていますが、洞察は大いに役立ちます、ありがとう

編集:created_at形式の説明を追加しました。

35
jct

私はこれに対する解決策を見つけたと信じています、キーはmysqlのDATE()関数で、DateTimeをちょうどDateに変換します:

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

ただし、これは実際にはLaravel Eloquentソリューションではありません。これは生のクエリであるためです。 。

$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"')
                            ));
46
jct

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
    });
44
dede

ここに私がそれをする方法があります。短い例ですが、クエリをより管理しやすくしました

$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
                        ->groupBy(DB::raw('Date(created_at)'))
                        ->orderBy('created_at', 'DESC')->get();
20
Quins

ほとんどのデータベースの問題と同様に、データベースを使用して解決する必要があります。

インデックスを使用してグループ化したいデータを保存すると、この問題を解決するための効率的で明確な方法を実現できます。

移行を作成する

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

モデルを更新する

<?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);
 }

使用法

   $viewsPerDay = PageView::perDay()->get();
3
henryallsuch

私は同じ問題を抱えていました、私は現在Laravel 5.3。

DATE_FORMAT()を使用します

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

これがお役に立てば幸いです。

3
Haidren Amalia

Mysql( Mysql/Mariadbヘルプについてはこちら )を使用して、フォーマットされた日付に基づいて結果をフィルタリングし、laravel-5.4で次のようなものを使用できます。

Model::selectRaw("COUNT(*) views, DATE_FORMAT(created_at, '%Y %m %e') date")->groupBy('date')->get();
3
ako

DATETIMEではなくDATEに従ってデータをグループ化するには、CAST関数を使用できます。

$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(DB::raw('CAST(created_at AS DATE)'));
2
gskhanal

警告:テストされていないコード。

$dailyData = DB::table('page_views')
    ->select('created_at', DB::raw('count(*) as views'))
    ->groupBy('created_at')
    ->get();
1
J.T. Grimes

Laravel 4.2をカーボンなしで使用する

ここでは、最近の10日間を取得し、同じ日のcreated_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>';

}

お役に立てれば

1
btaylor507
PageView::select('id','title', DB::raw('DATE(created_at) as date'))
          ->get()
          ->groupBy('date');
1
Shanu Singh

mysqlでは、laravelのようにタイムスタンプをパラメーターとして持つMONTHキーワードを追加できます。

Payement::groupBy(DB::raw('MONTH(created_at)'))->get();
0
Mohammed Raad

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;

`` `

0
Ifnot

これは古い質問であり、複数の回答があります。 laravel以下のドキュメントと私の経験によると、物事を処理するのに適した「雄弁な方法」はこれまでのところ

モデルに、このようなミューテーター/ゲッターを追加します

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

別の方法は、モデルに列をキャストし、$cast配列

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

ここでの問題は、Eloquentは常に列を文字列にキャストするため、このモデルでCarbonを再び使用できないことです。

それが役に立てば幸い :)

0
Sithira

次の方法でもこの問題を解決できます。

$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();
0
Rubel Ahmed