Mysql
 sql >> Base de données >  >> RDS >> Mysql

Éloquent dans lequel joindre plusieurs tables

Notez que la façon dont vous essayez de le faire, vous pouvez obtenir plusieurs lignes par article (une fois par liste associée). Une meilleure façon serait d'avoir un tableau d'annonces par article.

Si vous utilisez des modèles éloquents et que vous avez correctement configuré les relations, vous pouvez essayer ce qui suit :

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

Maintenant, chaque article doit avoir un listings propriété. Par exemple, pour le premier article, vous pouvez accéder aux listes de la manière suivante :

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

Notez que whereHas() créera probablement un EXISTS corrélé sous-requête pour chaque entrée dans $cats déployer. Si c'est trop lent, vous pouvez utiliser une requête JOIN comme :

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

Si vous n'utilisez pas eloquent, vous pouvez également effectuer vous-même le "chargement hâtif".

$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');
}