Laravel Eloquente ottenere risultati raggruppati per giorni

Attualmente ho una tabella di page_views che registra una riga per ogni volta che un visitatore accede a una pagina di registrazione ip dell’utente/id e l’id della pagina stessa. Vorrei aggiungere che il created_at colonna di tipo timestamp, in modo che include le ore/minuti/secondi. Quando cerco groupBy query, non del gruppo stesso giorno insieme a causa di secondi di differenza.

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
  ...                ...          ...

Mi piacerebbe ottenere risultati in base alle visite/giorno, in modo da poter ottenere qualcosa di simile:

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

Sto pensando bisogno di scavare in DB::raw (query) per raggiungere questo obiettivo, ma della comprensione sarebbe di grande aiuto, grazie

Di modifica: Aggiunta di un chiarimento di created_at formato.

InformationsquelleAutor jct | 2013-12-16

 

14 Replies
  1. 46

    Credo di aver trovato una soluzione a questo, la chiave è la funzione DATE() di mysql, che converte un valore di tipo DateTime in Data:

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

    Tuttavia, questo non è davvero un Laravel Eloquente soluzione, dal momento che questo è un raw query.Il seguente è ciò che mi è venuta in Eloquente-ish sintassi. La prima clausola where utilizza carbonio date da confrontare.

    $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"')
                                ));
    • Io sto usando questa soluzione e funziona alla grande! Una domanda però mi viene se volete gruppo che non ha Data, ma da un MESE, è possibile sostituire: Data(created_at), il Mese(created_at) Tuttavia, ciò che si vuole è quello di utilizzare YEAR_MONTH da MYSQL, ma che non funziona per me, ho paura, ho un errore. Non si vede la stessa cosa?
    • Si potrebbe avere usato Eloquente ->select($columns) e ->selectSub($query, $as) inoltre, per essere in grado di saltare la DB::raw() metodi 🙂
  2. 44

    È possibile utilizzare Carbonio (integrato in 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
        });
    • Ma questo i gruppi, DOPO l’esecuzione della query, il che significa che facendo elaborazione in php, che è molto più lento.
    • elaborazione in PHP non è sempre più lenta, ma tutto si riduce ai requisiti dell’applicazione. Questo È UN modo per farlo.
  3. 20

    Ecco come fare. Un breve esempio, ma di fatto la mia query molto più gestibile

    $visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
                            ->groupBy(DB::raw('Date(created_at)'))
                            ->orderBy('created_at', 'DESC')->get();
    • Questa è la risposta corretta. Il DATE() appartiene la funzione in GROUP BY clausola.
    • Questo è il modo in cui l’impaginazione sarà un lavoro facile! Grazie.
  4. 3

    Ho avuto lo stesso problema, attualmente sto usando Laravel 5.3.

    Io uso DATE_FORMAT()

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

    Speriamo che questo vi aiuterà.

    • In realtà vorrei usare questa soluzione, ma questo codice non può essere corretto. Hai errori di sintassi ovunque. Puoi postare il funzionamento del codice? Hai “create_at” errori di ortografia e groupBy-> che è sbagliato.
  5. 3

    È possibile filtrare i risultati in base al data formattata utilizzando mysql (Vedi qui per Mysql/Mariadb aiuto) e usare qualcosa come questo in laravel-5.4:

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

    Come la maggior parte dei problemi di database, essi dovrebbero essere risolti utilizzando il database.

    Memorizzare i dati che si desidera raggruppare e l’utilizzo di indici è possibile realizzare un efficace e chiaro il metodo per risolvere questo problema.

    Creare la migrazione

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

    Aggiornare il Modello

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

    Utilizzo

       $viewsPerDay = PageView::perDay()->get();
    • Vecchio post, ma non con questo metodo le risposte.
  7. 2

    Per raggruppare i dati in base alla DATA, invece di tipo DATETIME, è possibile utilizzare la funzione CAST.

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

    Avvertenza: il codice non testato.

    $dailyData = DB::table('page_views')
        ->select('created_at', DB::raw('count(*) as views'))
        ->groupBy('created_at')
        ->get();
    • Grazie J. T., questo dovrebbe funzionare se created_at potrebbe essere raggruppate ignorando le ore/minuti/secondi. È possibile raggruppare created_at da solo guardando anno/mese/giorno? Il created_at è il Laravel Schema generato il timestamp. Vedo 2 possibili soluzioni che richiedono la modifica del DB struttura: 1. Aggiungere Data colonna, che include solo la Data, non DateTime. 2. Ripetere l’eloquente modello e personalizzare il formato data / ora.
  9. 1

    Utilizzando Laravel 4.2 senza Carbonio

    Ecco come prendo ultimi dieci giorni e il conteggio di ogni riga con lo stesso giorno 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>';
    
    }

    Spero che questo aiuta

  10. 0

    in mysql, è possibile aggiungere al MESE keyword avere il timestamp come parametro
    in laravel si può fare come questo

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

    Ho costruito un laravel pacchetto per la realizzazione di statistiche : https://github.com/Ifnot/statistics

    È basato su eloquente, di carbonio e di indicatori così è davvero facile da usare. Potrebbe essere utile per l’estrazione data raggruppati indicatori.

    $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. 0

    So che questa è una VECCHIA Questione e non ci sono più risposte. Come mai secondo la documentazione e la mia esperienza su laravel sotto è il bene “Eloquente” di gestire le cose

    Nel modello, aggiungere un mutatore/Getter come questo

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

    Un altro modo è quello di gettare le colonne
    nel modello, inserire il $cast array

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

    La cattura è che non sarà in grado di utilizzare in Carbonio su questo modello in quanto Eloquente sempre in ghisa a colonna in corda

    Speranza che aiuta 🙂

  13. 0

    Si potrebbe anche risolvere questo problema nel modo seguente:

    $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();
    • Il codice è sempre buona, ma aiuta anche aggiungere alcuni commenti/contesto su come si affronta la domanda originale.

Lascia un commento