簡體   English   中英

Laravel Eloquent如何加入查詢而不是表?

[英]Laravel Eloquent how to join on a query rather than a table?

我想在Laravel實現這個目標:

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')作為一種解決方法。 只是想知道如何以雄辯的方式做到這一點? 謝謝。

如果你想在這種情況下出於效率原因進行單一查詢,那么Eloquent對你沒什么幫助,這是可能的,但是很麻煩。 對於這樣的情況,你有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();

如果更改getSql() 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 :: raw的子查詢,但只要你不在查詢中輸入用戶輸入它就不是不安全的。 即使在這種情況下,您也可以使用PDO安全地使用它。

至於Eloquent,你的產品模型甚至沒有price字段(它可能有一個返回關系對象的prices()函數)所以獲得一個與之相關的單一價格的Product模型是沒有意義的。

編輯:

您也可以急切地加載關系,即(假設您將模型關系設置為Trong Lam Phan的示例)

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

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

在Eloquent中,請關注我,您需要與普通的mysql查詢略有不同。 使用Model而不是復雜的查詢。

首先,您需要創建具有它們之間關系的Product和Price模型:

<?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']);

如果你不喜歡這種Eloquent方式,你可以像這樣使用Query Builder:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM