Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Eloquente em que com junção de várias tabelas


Observe que do jeito que você está tentando fazer isso, você pode obter várias linhas por item (uma vez por listagem relacionada). Uma maneira melhor seria ter uma matriz de listagens por item.

Se você usa modelos eloquentes e configurou as relações corretamente, você pode tentar o seguinte:
$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();

Agora cada item deve ter uma listings propriedade. Por exemplo, para o primeiro item, você pode acessar as listagens da seguinte maneira:
$item1 = $items[0];
$listings1 = $item1->listings;

Observe que whereHas() provavelmente criará um EXISTS correlacionado subconsulta para cada entrada no $cats variedade. Se isso for lento, você pode usar uma 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();

Se você não usa eloquente, você também pode fazer o "carregamento ansioso".
$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');
}