2013-12-16 6 views
21

В настоящее время у меня есть таблица page_views, которая записывает одну строку для каждого посещения посетителем страницы, записи ip/id пользователя и идентификатора самой страницы. Я должен добавить, что столбец created_at имеет тип: timestamp, поэтому он включает часы/минуты/секунды. Когда я пытаюсь выполнить запросы GroupBy, он не группирует те же дни вместе из-за разницы в секундах.Laravel Eloquent получить результаты, сгруппированные по дням

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

Я хотел бы получить результаты, основанные на Views/день, так что я могу получить что-то вроде:

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

Я думаю, мне придется копаться в БД :: сырец () запросов для достижения этого, но любое понимание поможет очень, спасибо

Редактировать: Добавлено уточнение формата created_at.

ответ

1

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

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

Благодаря J.T., это должна работать, если ** created_at ** может быть сгруппирована, игнорируя часы/минуты/секунду. Можно ли сгруппировать created_at, только глядя на год/месяц/день? ** created_at ** - это временные метки, созданные с помощью Laravel Schema. Я вижу 2 возможных решения, требующих изменения структуры БД: 1. Добавить колонку ** Дата **, которая включает только дату, а не DateTime. 2. Верните красноречивую модель и настройте формат timestamp. – jct

24

Я считаю, что я нашел решение этой проблемы, ключ функции DATE() в MySQL, который преобразует 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. Первый, где предложение использует даты углерода для сравнения.

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

Я использую это решение, и он отлично работает! Один вопрос у меня есть, хотя, если вы хотите, чтобы группа не по дате, а по месяцам, вы можете заменить: Дата (created_at) с Месяц (created_at) Однако то, что вы хотите использовать YEAR_MONTH из MYSQL, но это не сработает для меня. Боюсь, у меня ошибка. Вы видите то же самое? –

+0

Вы могли бы использовать Eloquent '-> select ($ columns)' и '-> selectSub ($ query, $ as)' также, чтобы иметь возможность пропускать методы 'DB :: raw() :) –

33

Вы можете использовать углеродистые (встроенный в 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 
    }); 
+13

Но это группирует его после запуска запроса, а это значит, что он обрабатывает php, что намного медленнее. – Benubird

+0

Блестящий ответ .... много спасибо человеку – hhsadiq

+4

Обработка в PHP не всегда медленнее, но все сводится к требованиям вашего приложения. Это способ сделать это. –

14

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

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

Это правильный ответ. Функция 'DATE()' принадлежит предложению 'GROUP BY'. – leek

2

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

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

в MySQL вы можете добавить МЕСЯЦ ключевое слово, имеющее метку времени в качестве параметра в Laravel вы можете сделать это, как этот

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

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

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

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

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

+0

Я действительно хочу использовать это решение, но этот код не может быть прав. У вас везде есть синтаксические ошибки. Можете ли вы опубликовать действующий код? У вас есть «create_at» с ошибкой и groupBy->, что неверно. –

0

Я построил пакет 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

Я знаю, что это старый вопрос, и есть несколько ответов.Как когда-либо в соответствии с Документами и моим опытом на Laravel ниже является хорошим «Красноречивым путем» обработка вещей

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

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

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

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

Загвоздка в том, что вы не сможете использовать Carbon на эту модель еще раз, так как Eloquent всегда будет отбрасывать столбец в строку

Надеется, что это помогает :)

0

Использованию Laravel 4.2 без углерода

Вот как я хватаю за последние десять дней и считать каждую строку же день 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>'; 

} 

Надеется, что это помогает

Смежные вопросы