Подтвердить что ты не робот

Как создать подзапрос с использованием Laravel Eloquent?

У меня есть следующий запрос Eloquent (это упрощенная версия запроса, состоящая из более where и orWhere, следовательно, очевидный обходной путь для этого - теория важна):

$start_date = //some date;

$prices = BenchmarkPrice::select('price_date', 'price')
->orderBy('price_date', 'ASC')
->where('ticker', $this->ticker)
->where(function($q) use ($start_date) {

    // some wheres...

    $q->orWhere(function($q2) use ($start_date){
        $dateToCompare = BenchmarkPrice::select(DB::raw('min(price_date) as min_date'))
        ->where('price_date', '>=', $start_date)
        ->where('ticker', $this->ticker)
        ->pluck('min_date');

        $q2->where('price_date', $dateToCompare);
    });
})
->get();

Как вы можете видеть, я pluck самая ранняя дата, которая встречается в моем или t < > . Это приводит к выполнению отдельного запроса для получения этой даты, который затем используется как параметр в основном запросе. Есть ли способ красноречиво объединить запросы вместе, чтобы сформировать подзапрос и, следовательно, только 1 вызов базы данных, а не 2?

Edit:

В соответствии с ответом @Jarek это мой запрос:

$prices = BenchmarkPrice::select('price_date', 'price')
->orderBy('price_date', 'ASC')
->where('ticker', $this->ticker)
->where(function($q) use ($start_date, $end_date, $last_day) {
    if ($start_date) $q->where('price_date' ,'>=', $start_date);
    if ($end_date) $q->where('price_date' ,'<=', $end_date);
    if ($last_day) $q->where('price_date', DB::raw('LAST_DAY(price_date)'));

    if ($start_date) $q->orWhere('price_date', '=', function($d) use ($start_date) {

        // Get the earliest date on of after the start date
        $d->selectRaw('min(price_date)')
        ->where('price_date', '>=', $start_date)
        ->where('ticker', $this->ticker);                
    });
    if ($end_date) $q->orWhere('price_date', '=', function($d) use ($end_date) {

        // Get the latest date on or before the end date
        $d->selectRaw('max(price_date)')
        ->where('price_date', '<=', $end_date)
        ->where('ticker', $this->ticker);
    });
});
$this->prices = $prices->remember($_ENV['LONG_CACHE_TIME'])->get();

Блоки orWhere приводят к тому, что все параметры в запросе внезапно становятся неупорядоченными. Например. where price_date >= 2009-09-07. Когда я удаляю orWheres, запрос работает нормально. Почему это?

4b9b3361

Ответ 1

Вот как вы делаете подзапрос, где:

$q->where('price_date', function($q) use ($start_date)
{
   $q->from('benchmarks_table_name')
    ->selectRaw('min(price_date)')
    ->where('price_date', '>=', $start_date)
    ->where('ticker', $this->ticker);
});

К сожалению, orWhere требует явно предоставленного $operator, иначе он вызовет ошибку, поэтому в вашем случае:

$q->orWhere('price_date', '=', function($q) use ($start_date)
{
   $q->from('benchmarks_table_name')
    ->selectRaw('min(price_date)')
    ->where('price_date', '>=', $start_date)
    ->where('ticker', $this->ticker);
});

РЕДАКТИРОВАТЬ: вам действительно нужно указать from в закрытии, иначе он не будет строить правильный запрос.