Laravel leftJoin 只加入右表的最后一条记录并按它排序

Posted

技术标签:

【中文标题】Laravel leftJoin 只加入右表的最后一条记录并按它排序【英文标题】:Laravel leftJoin only last record of right table and order by it 【发布时间】:2021-05-03 17:31:00 【问题描述】:

我有两张桌子。 1) 产品 2) 价格

-------------------------
-       products        -
-------------------------
- id         | int      -
- name       | varchar  -
- created_at | datetime -
- updated_at | datetime -
-------------------------

----------------------------
-          prices          -
----------------------------
- id            | int      -
- product_id    | int      -
- sale_price    | int      -
- regular_price | int      -
- created_at    | datetime -
- updated_at    | datetime -
-----------------------------

我想搜索产品并从价格表中获取每种产品的最后价格。我用这个:

class Product extends Model

   public function lastPrice()
    
        return $this->hasOne(Price::class)->orderBy('id', 'DESC');
    


我使用以下命令获取具有最新价格的产品列表:

$products=Product::with('lastPrice')->paginate(9);

我的问题是:我想按最高/最低价格订购结果。我将如何做到这一点?

【问题讨论】:

这能回答你的问题吗? Laravel leftJoin only last record of right table 【参考方案1】:

我相信使用laravel 6 或更高版本您可以在addSelect() 子句中使用相关子查询作为

Product::addSelect(['latest_price' =>
                        Price::select('price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1)
])->orderBy('latest_price','desc')
  ->paginate(9);
  

因此,我们将从上面获取产品数据以及数据库中的最新价格列,以便您可以在latest_price上应用排序

编辑如果您有有限的列可供选择,例如 sale_price,您可以添加另一个子查询,但如果您想从价格表中选择整行,请查看另一种使用 join/exists 的方法

Product::addSelect(['sale_price' =>
                        Price::select('sale_price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1),
                    'regular_price' =>
                        Price::select('regular_price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1),

])->orderBy('sale_price','desc')
  ->orderBy('regular_price','desc')
  ->get();

【讨论】:

谢谢,M Khalid Junaid 给了我 1/2 的解决方案,但如果价格表有其他列(如 sale_price 和 regular_price),我怎样才能得到它们。按销售价格订购 我已经为您的问题更新了我的答案,并发布了另一个使用不同方法的答案【参考方案2】:

您可以从价格表中选择最新行以及产品数据,我现在可以想到两种方法

 // Approach 1
 Product::join('prices as a', 'products.id', '=', 'a.product_id')
        ->leftJoin('prices as a1', function ($join) 
            $join->on('a.product_id', '=', 'a1.product_id')
                 ->whereRaw(DB::raw('a.id < a1.id'));
           )
        ->whereNull('a1.product_id')
        ->select('products.*', 'a.*')
        ->orderBy('sale_price','desc')
        ->orderBy('regular_price','desc')
        ->get();

// Approach 2 with whereExists
 Product::join('prices as a', 'products.id', '=', 'a.product_id')
        ->whereExists(function ($query) 
           $query->select(DB::raw(1))
                 ->from('prices as b')
                 ->whereRaw(DB::raw('a.product_id = b.product_id'))
                 ->havingRaw('max(b.id) = a.id');
        )
        ->select('products.*', 'a.*')
        ->orderBy('sale_price','desc')
        ->orderBy('regular_price','desc')
        ->get();

【讨论】:

以上是关于Laravel leftJoin 只加入右表的最后一条记录并按它排序的主要内容,如果未能解决你的问题,请参考以下文章

mysql left join中where和on条件的区别

SQL语句中LEFT JOIN和RIGHT JOIN 以及INNER JOIN的区别

Oracle_SQL 连接和子查询

sql(join on 和where的执行顺序)

sql(join on 和where的执行顺序)

sql(join on 和where的执行顺序)