2014-11-21 12 views
12

Aşağıdaki Eloquent sorgu var (Bu nedenle daha where s ve orWhere s arasında bu konuda gidiş görünürdeki dolambaçlı bir yol oluşan bir sorgunun basitleştirilmiş bir sürümüdür - teori neyin önemli olduğunu):Laravel Eloquent kullanarak nasıl bir alt sorgu oluşturulur?

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

Ben start_date benim veya daha sonra pluck görüyorum en erken tarihini görebiliyorum. Bu, daha sonra ana sorguda bir parametre olarak kullanılan bu tarihi almak için çalıştırılan ayrı bir sorgu ile sonuçlanır. Sorguları bir alt sorgu oluşturmak için birlikte yerleştirmenin bir yolu var mı ve bu nedenle 2 yerine yalnızca 1 veritabanı çağrısı var mı?

Düzenleme: bu benim sorgu

Jarek cevabı @ gereğince:

$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 blok sorguda tüm parametreleri aniden tırnaksız olmaya neden oluyor. Örneğin. WHERE price_date >= 2009-09-07. orWheres'u kaldırdığımda sorgu düzgün çalışıyor. Bu neden?

cevap

16

Bu, bir alt sorgu yapmak nasıl: aksi takdirde, bir hata döndürür, maalesef orWhere açıkça $operator sağlanan gerektirir

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

senin durumunda böyle:

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

DÜZENLEME: Aslında kapatma içinde from belirtmeniz gerekir, aksi takdirde doğru sorgu oluşturmayacaktır.

+3

Artı 1 - Doğru cevap budur. OP bu cevabı kabul ettiği anda benimkini sileceğim. –

+0

Yine iyi görünüyor, ancak ciltleme doğru değil. Sorguya "$ this-> ticker" parametresinin bir hatayla sonuçlandığını buldum. Örneğin. '... VE Ticker = ukc0tr01 INDEX) ...' – harryg

+0

Aynı tarih için de geçerlidir: 'WHERE price_date <= 2014-07-31'. Neden tarihte tırnak yok? – harryg