Mysql
 sql >> Database >  >> RDS >> Mysql

Eloquente in cui con unisci più tavoli

Nota che il modo in cui stai cercando di farlo, potresti ottenere più righe per articolo (una volta per elenco correlato). Un modo migliore sarebbe avere una serie di inserzioni per articolo.

Se utilizzi modelli eloquenti e hai impostato correttamente le relazioni, potresti provare quanto segue:

$cats = [1, 2, 3];

$query = Item::with('listings');
foreach ($cats as $cat) {
    $query->whereHas('catitems', function($q) use($cat) {
        $q->where('id', $cat);
    });
}
$items = $query->get();

Ora ogni articolo dovrebbe avere un listings proprietà. Ad esempio per il primo articolo puoi accedere alle inserzioni nel modo seguente:

$item1 = $items[0];
$listings1 = $item1->listings;

Nota che whereHas() probabilmente creerà un EXISTS correlato sottoquery per ogni voce nel $cats Vettore. Se è troppo lento, puoi utilizzare una query JOIN come:

$items = Item::with('listings')
    ->join('catitem_item', 'catitem_item.item_id', '=', 'items.id')
    ->whereIn('catitem_item.catitem_id', $cats)
    ->groupBy('items.id')
    ->having(DB::raw('count(*)'), '=', count($cats))
    ->select('items.*')
    ->get();

Se non usi l'eloquente, puoi anche fare il "caricamento ansioso" da solo.

$items = DB::table('items')
    ->join('catitem_item', 'catitem_item.item_id', '=', 'items.id')
    ->whereIn('catitem_item.catitem_id', $cats)
    ->groupBy('items.id')
    ->having(DB::raw('count(*)'), '=', count($cats))
    ->select('items.*')
    ->get()
    ->keyBy('id');

foreach ($items as $item) {
    $item->listings = [];
}

$itemIds = $items->pluck('id');
$listings = DB::table('listings')
    ->join('item_listing', 'item_listing.listing_id', '=', 'listings.id')
    ->whereIn('item_listing.item_id', $itemIds)
    ->groupBy('listings.id')
    ->select('listings.*', DB::raw('group_concat(item_listing.item_id) as item_ids'))
    ->get();

foreach ($listings as $listing) {
    $itemIds = explode(',', $listing->item_ids);
    foreach ($itemIds as $itemId) {
        $items[$itemId]->listings[] = $listing;
    }
    $listing->forget('item_ids');
}