sql >> Base de Datos >  >> RDS >> Mysql

Elocuente en el que se unen varias tablas

Tenga en cuenta que, de la forma en que intenta hacerlo, es posible que obtenga varias filas por elemento (una vez por lista relacionada). Una mejor manera sería tener una variedad de listados por artículo.

Si usa modelos elocuentes y ha configurado las relaciones correctamente, puede intentar lo siguiente:

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

Ahora cada artículo debe tener un listings propiedad. Por ejemplo, para el primer artículo, puede acceder a los listados de la siguiente manera:

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

Tenga en cuenta que whereHas() probablemente creará un EXISTS correlacionado subconsulta para cada entrada en $cats formación. Si eso es demasiado lento, puede usar una consulta JOIN como:

$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 no usa elocuente, también puede hacer la "carga ansiosa" usted mismo.

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