Подтвердить что ты не робот

Laravel Eloquent получает результаты, сгруппированные по дням

В настоящее время у меня есть таблица page_views, которая записывает одну строку для каждого посещения посетителем страницы, записи ip/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.

4b9b3361

Ответ 1

Я считаю, что нашел решение этого, ключ - это функция DATE() в mysql, которая преобразует DateTime в просто Date:

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

Однако это не действительно решение Laravel Eloquent, так как это сырой запрос. Следующее - это то, что я придумал в синтаксисе Eloquent-ish. Первый, где предложение использует даты углерода для сравнения.

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

Ответ 2

Вы можете использовать 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
    });

Ответ 3

Вот как я это делаю. Короткий пример, но сделавший мой запрос более управляемым

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

Ответ 4

У меня была такая же проблема, я в настоящее время использую Laravel 5.3.

Я использую DATE_FORMAT()

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

Надеюсь, это поможет вам.

Ответ 5

Вы можете отфильтровать результаты на основе форматированной даты, используя mysql (см. Здесь для справки Mysql/Mariadb) и использовать что-то подобное в laravel-5.4:

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

Ответ 6

Как и большинство проблем с базой данных, они должны решаться с помощью базы данных.

Храня данные, которые вы хотите сгруппировать, и используя индексы, вы можете найти эффективный и понятный метод решения этой проблемы.

Создать миграцию

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

Ответ 7

Чтобы группировать данные в соответствии с DATE вместо DATETIME, вы можете использовать функцию CAST.

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

Ответ 8

Предупреждение: непроверенный код.

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

Ответ 9

Использование Laravel 4.2 без Carbon

Вот как я хватаю последние десять дней и подсчитываю каждую строку с тем же днем ​​created_at timestamp.

$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>';

}

Надеюсь, что это поможет

Ответ 10

в mysql вы можете добавить ключевое слово MONTH с меткой времени в качестве параметра в laravel вы можете сделать это, как это

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

Ответ 11

Я создал пакет 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;

`` `

Ответ 12

Я знаю, что это вопрос OLD, и есть несколько ответов. Как бы то ни было согласно документам и моему опыту на laravel ниже, это хороший "Красноречивый способ" обработки вещей.

В вашей модели добавьте мутатор /Getter, как этот

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

Другим способом является создание столбцов в вашей модели заполнить массив $cast

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

Ловушка здесь заключается в том, что вы не сможете использовать Carbon на этой модели снова, поскольку Eloquent всегда будет отличать колонку в строку

Надеюсь, это поможет:)

Ответ 13

Вы также можете решить эту проблему следующим образом:

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

Ответ 14

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