首页 > 解决方案 > 使用嵌套关系的结果查询关系

问题描述

在这里,我有下面的代码,我想过滤我的酒店并为每家酒店选择最低价格的房间:

 $city_id = $request->get('city_id');
            $stars = $request->get('grade_stars');
            $type_id = $request->get('accommodation_type_id');
            $from_date = $request->get('from_date');
            $to_date = $request->get('to_date');
            $data = Accommodation::with(['city','accommodationRoomsLimited.roomPricingHistorySearch' =>function($query) use($from_date,$to_date){
                $query->whereDate('from_date', '<=', $from_date);
                $query->whereDate('to_date', '>=', $to_date);
                }])
                ->whereIn('city_id',$city_id)
                ->whereIn('grade_stars',$stars)
                ->orWhere('accommodation_type_id',$type_id)
                ->paginate(10);
            return $data;

这是我的住宿模式:

    public function accommodationRoomsLimited()
{
    return $this->Hasmany(AccommodationRoom::class)->select('id', 'accommodation_id');
}

在我的住宿房间模型中:

  public function roomPricingHistorySearch()
{
    return $this->hasOne(RoomPricingHistory::class,'accommodation_room_id','id')->orderBy('sales_price','ASC');
}

我有一个名为房间定价历史记录的表,它记录每天的房间价格这是我在 api 中的输出,我想在 room_pricing_history_search 中选择 1 个具有最低 sales_price 的房间:

"accommodation_rooms_limited": [
        {
            "id": 4859,
            "accommodation_id": 47,
            "room_pricing_history_search": {
                "id": 15741,
                "accommodation_room_id": 4859,
                "net_price": null,
                "sales_price": 50,

                "created_at": "2019-05-25 13:30:00",
                "updated_at": "2019-05-25 13:30:00"
            }
        },
        {
            "id": 4860,
            "accommodation_id": 47,
            "room_pricing_history_search": {
                "id": 4990,
                "accommodation_room_id": 4860,
                "net_price": null,
                "sales_price": 1760000,

                "created_at": "2019-05-25 13:30:00",
                "updated_at": "2019-05-25 13:30:00"
            }
        },
        {
            "id": 4861,
            "accommodation_id": 47,
            "room_pricing_history_search": {
                "id": 4991,
                "accommodation_room_id": 4861,
                "net_price": null,
                "sales_price": 2270000,

                "created_at": "2019-05-25 13:30:00",
                "updated_at": "2019-05-25 13:30:00"
            }
        },
        {
            "id": 4862,
            "accommodation_id": 47,
            "room_pricing_history_search": {
                "id": 4992,
                "accommodation_room_id": 4862,
                "net_price": null,
                "sales_price": 2780000,

                "created_at": "2019-05-25 13:30:00",
                "updated_at": "2019-05-25 13:30:00"
            }
        }
    ]
},

标签: phpmysqllaravel

解决方案


从选择房间而不是酒店开始,然后按酒店分组可能更简单。

您可以使用原始表达式来获得最低房价:

$raw = DB::raw('min(price) as min_price');

然后从房间表中选择并按酒店 ID 分组:

Room::join('hotels', 'hotels.id' ,'=', 'rooms.hotel_id')
   ->whereDate('rooms.from_date', '<=', $from_date)
   ->whereDate('rooms.to_date', '>=', $to_date)
   ->select('hotels.*', $raw)
   ->groupBy('hotels.id')
   ->get()

Jonathan Reinink 最近的演讲 Eloquent Performance Patterns可能也会让您感兴趣。他谈到了与你类似的查询,看起来他谈到的拉取请求将使这些查询更容易已经合并到 Laravel 6.0 中。所以从 Laravel 6.0 你应该可以做这样的事情:

return Hotel::addSelect(['lowest_price' => function ($query) {
    $query->select('price')
        ->from('rooms')
        ->whereColumn('hotel_id', 'hotels.id')
        ->orderBy('price', 'asc')
        ->limit(1);
}])->get();

推荐阅读