Как фильтровать по месяцам в sql - PullRequest
0 голосов
/ 12 ноября 2018

Как оптимизировать мой код с помощью SQL-запросов

$collection->filter(function ($item) use ($i) {
  return $item->created_at->month == $i->month;
})->count();

Я хочу вместо функции фильтрации в коллекции фильтровать в sql, чтобы она могла быть быстрее

вот функция:

$data = [];
    switch ($range) {
        //monthly
        case self::$timeRanges[0]:
            for ($i = Carbon::now()->copy()->subYear()->endOfMonth(); $i <= Carbon::now()->subMonth()->endOfMonth(); $i->addMonths(1)) {
                $data[$i->month] = $collection->filter(function ($item) use ($i) {
                    return $item->created_at->month == $i->month;
                })->count();
            }
            break;
        //weekly
        case self::$timeRanges[1]:
            $collection = $collection->where('created_at', '>=', Carbon::now()->subWeek()->endOfWeek()->subWeeks(5))->where('created_at', '<=', Carbon::now()->subWeek()->endOfWeek());
            for ($i = Carbon::now()->copy()->subWeek()->endOfWeek()->subWeeks(5); $i <= Carbon::now()->copy()->subWeek()->endOfWeek(); $i->addWeeks(1)) {
                $data[$i->weekOfMonth] = $collection->filter(function ($item) use ($i) {
                    return $item->created_at->weekOfYear == $i->weekOfYear;
                })->count();
            }
            break;
    }
    return ($data);

спасибо за помощь и хорошего дня!

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Просто чтобы расширить ответ @ Elie, вам даже не нужно использовать необработанный запрос. Laravel прекрасно обслуживает условия даты, и это очень хорошо задокументировано на странице Queries .

$desiredMonth = 12;

Model::whereMonth('created_at', $desiredMonth)->get();

Однако это не совсем отвечает на поставленный вопрос. Что нам нужно сделать, это получить все релевантные результаты, а затем отфильтровать полученные результаты по месяцам. Я считаю, что будет гораздо эффективнее и быстрее сделать это, извлекая все результаты из SQL и затем фильтруя их, как вы, но с меньшим количеством итеративного кода:

$collection = Model::whereYear(2018)->get();

$months = $collection->groupBy(function ($item, $key) {
    return $item->created_at->month;
});

$months->toArray();

[
    '1' => [[...],[...],[...]],
    '2' => [[...],[...],[...]],
    '3' => [[...],[...],[...]],
    '4' => [[...],[...],[...]],
    '5' => [[...],[...],[...]],
    '6' => [[...],[...],[...]],
    '7' => [[...],[...],[...]],
    '8' => [[...],[...],[...]],
    '9' => [[...],[...],[...]],
    '10' => [[...],[...],[...]],
    '11' => [[...],[...],[...]],
    '12' => [[...],[...],[...]],
]

Кроме того, если вы настаиваете на использовании SQL для фильтрации, вы можете сделать groupBy:

Model::groupBy(\DB::raw('MONTH(created_at) as month'))->get();

Вам нужно будет провести собственное тестирование, которое быстрее или, по крайней мере, наиболее эффективно. Кроме того, некоторые базы данных не допускают нескольких группировок (которых у нас нет, но вы можете добавить их) без изменения их конфигурации, поэтому мой личный главный приз - оригинальный подход, если вы не работаете с огромным набором данных.

0 голосов
/ 12 ноября 2018

Попробуйте это:

Model::where(\DB::raw('MONTH(created_at)') , $month )->get();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...