Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to nesting when performing a left join and multiple inner joins

Consider the following fictitious scenario:

Entity relationship diagram

How would I go about getting a list of all the categories (distinct or otherwise, it doesn't matter) for each customer, even if a customer hasn't ordered any products?

Also assume that we don't have navigation properties, so we'll need to use manual joins.

This is my attempt which uses nesting:

var customerCategories = from c in context.Customers
                         join o in context.Orders on c.CustomerId equals o.CustomerId into orders
                         select new
                         {
                             CustomerName = c.Name,
                             Categories = (from o in orders
                                           join p in context.Products on o.ProductId equals p.ProductId
                                           join cat in context.Category on p.CategoryId equals cat.CategoryId
                                           select cat)
                         };

Is there a different (possibly better way) to achieve the same outcome?

Alternative: Multiple Left (Group) Joins

var customerCategories = from customer in context.Customers
                         join o in context.Orders on customer.CustomerId equals o.CustomerId into orders
                         from order in orders.DefaultIfEmpty()
                         join p in context.Products on order.ProductId equals p.ProductId into products
                         from product in products.DefaultIfEmpty()
                         join cat in context.Categories on product.CategoryId equals cat.CategoryId into categories
                         select new
                         {
                             CustomerName = c.Name,
                             Categories = categories
                         };
like image 529
Zac Blazic Avatar asked Dec 14 '25 16:12

Zac Blazic


1 Answers

I recreated your table structure and added some data so that I could get a better idea what you were trying to do. I found a couple of ways to accomplish what you want but I'm just going to add this method. I think it's the most concise and I think it's pretty clear.

Code

var summaries = Customers.GroupJoin(Orders,
    cst => cst.Id,
    ord => ord.CustomerId,
    (cst, ord) => new { Customer = cst, Orders = ord.DefaultIfEmpty() })
    .SelectMany(c => c.Orders.Select(o => new
        {
            CustomerId = c.Customer.Id,
            CustomerName = c.Customer.Name,
            Categories = Categories.Where(cat => cat.Id == c.Customer.Id)
        }));

Output

LINQ Output

Table Structure

Table Structure

Table Data

Table Data

like image 152
phillip Avatar answered Dec 17 '25 07:12

phillip



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!