2016-06-12 88 views
3

我想在Laravel來實現這一目標:Laravel Eloquent如何加入查詢而不是表格?

SELECT * FROM products JOIN 
(SELECT product_id, MIN(price) AS lowest FROM prices GROUP BY product_id) AS q1 
ON products.id = q1.product_id 
ORDER BY q1.lowest; 

我寫了這個,但顯然有些不妥:

$products = new Product(); 
$products = $products->join(
    Price::whereNotNull('price')->select('product_id', DB::raw('min(price) as lowest'))->groupBy('product_id'), 'products.id', '=', 'product_id' 
    )->orderBy('lowest')->get(); 

我得到的錯誤:

ErrorException in Grammar.php line 39: 
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string. 

我目前使用join(DB::raw('(SELECT product_id, MIN(price) AS lowest FROM prices WHERE price IS NOT NULL GROUP BY product_id) AS q1'), 'products.id', '=', 'q1.product_id')作爲解決方法。只是想知道如何以雄辯的方式做到這一點?謝謝。

+0

你能告訴我們,你想給產品什麼?因爲我沒有得到你在做什麼,因爲我的SQL技能很低 –

+0

@AchrafKhouadja我想以最低的價格訂購我的'產品'表 – Harrison

回答

0

在Eloquent中,跟着我,你需要考慮與普通的mysql查詢有點不同。使用模型而不是複雜的查詢。

首先,你需要與他們之間的關係,建立產品與價格型號:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Product extends Model 
{ 
    public function prices() 
    { 
     return $this->hasMany('\App\Price'); 
    } 
} 

class Price extends Model 
{ 
    public function product() 
    { 
     return $this->belongsTo('\App\Product'); 
    } 
} 

然後,您需要選擇所有產品:

$products = \App\Product::get(); 
foreach ($products as $product) 
{ 
    $minPrice = $product->prices->min('price'); 
    echo 'Min price of product ' . $product->name . ' is: ' . $minPrice; 
} 

編輯

如果您對性能有問題,只需獲取產品的ID。

$products = \App\Product::get(['id']); 

如果你不喜歡侃侃而談的這種方式,你可以使用查詢生成器這樣的:

$result = \App\Price::join('products', 'prices.product_id', '=', 'products.id') 
       ->select('product_id', 'name', \DB::raw("MIN(price) AS min_price")) 
       ->groupBy('product_id') 
       ->orderBy('min_price') 
       ->get(); 

,或者你可以做這樣的:

\App\Price::join('products', 'prices.product_id', '=', 'products.id') 
     ->selectRaw("name, MIN(price) AS min_price") 
     ->groupBy('product_id') 
     ->orderBy('min_price') 
     ->get() 
+0

我不想獲得我的整個'產品'表的集合,並使用' sortBy',這非常慢。 – Harrison

+0

是的,你說得對。如果產品表是巨大的,它不起作用。我編輯了我的答案,希望對你有用。 –

0

如果你想在這種情況下,出於效率原因做一個單一的查詢雄辯不會幫助你很多,這是可能的,但是很麻煩。對於這種情況你有QueryBuilder。

DB::table('products') 
    ->join(
     DB::raw('(SELECT product_id, MIN(price) AS lowest FROM prices GROUP BY product_id) AS q1'), 
     'products.id', '=', 'q1.product_id' 
    ) 
    ->orderBy('q1.lowest')->get(); 

如果更改get()getSql()您會收到以下

select * from `products` inner join 
(SELECT product_id, MIN(price) AS lowest FROM prices GROUP BY product_id) AS q1 
on `products`.`id` = `q1`.`product_id` order by `q1`.`lowest` asc 

不幸的是,據我知道你不能使用沒有DB ::生一個子查詢,但它不是不安全,只要因爲您不會將用戶輸入置於查詢中。即使在這種情況下,您也可以使用PDO安全地使用它。

至於口才好,你的產品型號甚至沒有一個price場(它可能有一個prices()函數返回一個關係對象),所以它是沒有意義的獲得Product模型單一價格asociated它。

編輯:

eager load的關係就可以了,即(假設你有設置爲仲林藩的例子模型關係)

$products = Product::with('prices')->get(); 
foreach ($products as $product) 
{ 
    $minPrice = $product->prices->min('price'); 
    // Do something with $product and $minPrice 
} 

這將只運行一個查詢,但min()操作不是由數據庫完成的。

相關問題