2014-11-21 78 views
12

我有以下雄辯查詢(這是由更where S和orWhere小號。因此要對這個明顯的迂迴的方式查詢的簡化版本 - 理論是什麼是最重要):如何使用Laravel雄辯創建子查詢?

$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該日或之後我start_date發生的最早日期。這會導致運行一個單獨的查詢以獲取此日期,然後將其用作主查詢中的參數。有沒有一種雄辯的方式將查詢嵌入到一起形成子查詢,因此只有1個數據庫調用而不是2個?

編輯:每@亞雷克的回答

因爲這是我的查詢:

$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查詢工作正常。爲什麼是這樣?

回答

16

這是你怎麼做,其中一個子查詢:

$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,否則它不會構建正確的查詢。

+3

加1 - 這是正確的答案。一旦OP接受這個答案,我會立即刪除它。 – 2014-11-21 16:56:18

+0

再次看起來不錯,除了綁定不是很對。我發現'$ this-> ticker'參數被輸入到未加引用的查詢中,導致錯誤。例如。 '... AND ticker = ukc0tr01 INDEX)...' – harryg 2014-11-21 17:19:30

+0

日期也一樣:'WHERE price_date <= 2014-07-31'。爲什麼在日期前沒有引號? – harryg 2014-11-21 17:21:24