如何使用Laravel Eloquent创建子查询?

时间:2014-11-21 15:23:38

标签: php laravel laravel-4 eloquent

我有以下Eloquent查询(这是一个查询的简化版本,它由更多whereorWhere组成,因此有明显的迂回方式 - 理论是什么& #39;重要):

$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();

您可以看到pluckstart_date之后或之后发生的最早日期$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(); 。这会导致运行单独的查询以获取此日期,然后将其用作主查询中的参数。有没有一种方法可以将查询嵌入到一起形成子查询,从而只有1个数据库调用而不是2个?

修改

根据@ Jarek的回答,这是我的疑问:

orWhere

WHERE块导致查询中的所有参数突然变为不加引号。例如。 >= 2009-09-07 {price_date {1}}。当我删除orWheres时,查询工作正常。这是为什么?

1 个答案:

答案 0 :(得分:23)

这是你如何做子查询:

$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,否则它将无法构建正确的查询。