Laravel красноречиво, где есть первая дата после указанной c даты - PullRequest
1 голос
/ 25 марта 2020

У меня есть две связанные таблицы:

publications:

| id | name    |
| 1  | Test    |
| 2  | Example | 

publication_dates:

| id | publication_id | date       |
| 1  | 1              | 2020-02-01 |
| 2  | 1              | 2020-02-10 |
| 3  | 1              | 2020-01-25 |
| 4  | 2              | 2020-01-10 |
| 5  | 2              | 2019-12-15 |

Теперь, например, я хотел бы получить все publications, где первая дата publication_dates после 2020-01-01. Поэтому я попробовал следующее:

$publications = Publication::whereHas('dates', function($query) {
   $query->whereRaw("MIN(date) > '2020-01-10'");
});

Но это возвращает следующую ошибку:

SQLSTATE [HY000]: Общая ошибка: 1111 Неправильное использование групповой функции

, который возвращается к MIN(date). Поэтому у меня остается вопрос, как мне получить все публикации с первой датой после 2020-01-01 или любой другой указанной c датой. Из приведенного выше примера я ожидаю получить публикацию с идентификатором 1, поскольку первая дата 2 равна 2019-12-15

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Вы должны отменить запрос logi c, и тогда вы можете использовать отсутствие связи .

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;

$date = Carbon::create('2020-01-10');
$publications = Publication::whereDoesntHave('dates', function(Builder $query) use ($date) {
    $query->where('date', '<', $date->toDateString());
});

Вы также можете go далее и сделать метод локальной области видимости для построитель запросов в модели

// Publication model


/**
 * Scope a query to only include publications that has date newer than $date
 *
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @param string|object Carbon $date
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeDatesNewerThan($query, Carbon $date)
{
    return $query->whereDoesntHave('dates', function(Builder $query) use ($date) {
        $query->where('date', '<', $date->toDateString());// or set '<=' if more appropriate
    });
}

Затем где-то в коде, т.е. новее, чем за последние 30 дней

// $publications = Publication::datesNewerThan(Carbon::now()->subDays(30))->get();
1 голос
/ 25 марта 2020

Я предполагаю, что ошибка в том, что вы используете агрегатную функцию без правильного предложения group by. Вы можете использовать соединение для решения этой проблемы. но здесь немного другой подход, использующий объединение подзапросов .

$firstDates = PublicationDate::groupBy('publication_id')
->selectRaw('publication_id, MIN(date) as first_date'); // assuming you have a model called PublicationDate for the publication_dates table

Publication::joinSub($firstDates, 'first_dates', function($join){
    $join->on('first_dates.publication_id', '=', 'publications.id')
         ->where('first_date', '>','2020-01-10');
})->get();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...