#mysql #laravel #laravel-query-builder
Вопрос:
У меня есть столик exampleTable
:
------------ --------
| created_at | result |
------------ --------
| 2021-05-21 | 3 |
| 2021-05-21 | 4 |
| 2021-05-22 | 5 |
| 2021-05-23 | 6 |
| 2021-05-23 | 7 |
Я хочу результата:
------------ --------
| day | sumAll |
------------ --------
| 2021-05-01 | 0 |
| 2021-05-02 | 0 |
| 2021-05-03 | 0 |
....
| 2021-05-21 | 7 |
| 2021-05-22 | 5 |
| 2021-05-23 | 13 |
....
| 2021-05-29 | 0 |
| 2021-05-30 | 0 |
| 2021-05-21 | 0 |
И это мой вопрос:
$results = ExampleTable::select(
DB::raw("DATE_FORMAT(created_at,'%Y-%M-%d') as day"),
DB::raw('sum(result) as sumAll')
)
->whereMonth("created_at", '05')
->whereYear("created_at", '2021')
->groupBy('day')
->get();
Но это не показывает, если дата не существует.
Я хочу, чтобы значение дня с датой и значением результата было равно 0, если данные не существуют
Комментарии:
1. Вы должны сгенерировать список дат (календарь), затем добавить в него свои данные и, наконец, подвести итоги. Метод генерации зависит от точной версии MySQL (или вы можете использовать статическую служебную таблицу с номерами от 1 до 31).
2. Является
created_at
ли текстовый столбец?3. как использовать эквалайзер?. нет, это отметка времени, но я удаляю время в этом вопросе.
Ответ №1:
- Создайте новую коллекцию с помощью
php artisan make:collection \App\Collections\ExampleCollection
- Сделайте следующее:
<?php
namespace AppCollections;
use DatePeriod;
use IlluminateDatabaseEloquentCollection;
class ExampleCollection extends Collection
{
public function withDefaults()
{
$date = $this->sortBy('day')[0]->day->firstOfYear();
$days = array_map(function($day) {
return $day->format('Y-m-d');
}, [...new DatePeriod("R11/{$date->toIso8601ZuluString()}/P1D")]); // e.g. 2021-01-01T00:00:00Z
$collection = array_fill_keys(array_fill_keys($days, []));
foreach($this as $item) {
$collection[$item->day->format('Y-m-d')] = $item;
}
return collect($collection);
}
}
- Внутри вашей
ExampleTable
модели добавьте это:
public function newCollection(array $models = [])
{
return new ExampleCollection($models);
}
- Используйте его вот так:
$results = ExampleTable::select(
DB::raw("DATE_FORMAT(created_at,'%Y-%M-%d') as day"),
DB::raw('sum(result) as sumAll')
)
->whereMonth("created_at", '05')
->whereYear("created_at", '2021')
->groupBy('day')
->get()
->withDefaults();
Комментарии:
1. спасибо, это замечательно. Я обнаружил ошибку в функции withDefault, но это не проблема, я изменяю это.
2. Рад помочь 🙂 Где вы нашли ошибку? Я сейчас же исправлю свой ответ