2013-03-02 5 views
1

D'accord, coincé pour un jour maintenant, s'il vous plaît quelqu'un donner un coup de main!Comment faire une requête LINQ pour cela?

Je souhaite sélectionner la quantité de TOUT article possible d'un client spécifique, qu'il ait ou non commandé l'article. Donc, s'ils ne l'ont pas commandé (c'est-à-dire qu'il ne figure pas dans la table Commandes), renvoyez une valeur de 0 pour la quantité.

CommandesCustomerId Itemid Quantité

Articles ItemId ITEMNAME

Les clients CustomerId CustomerName

Je suppose que cela impliquera une sorte de sous-requête, mais vraiment pas sûr.

from c in customers 
join o in Orders 
on c.CustomerId == o.CustomerId 
select c.CustomerName, o.Quantity 
where c.CustomerId == customerId 
+0

Je ne suis pas ce que vous entendez par «qu'un client spécifique a». Comment un client "a" un article? –

+0

@TimSchmelter mis à jour. J'en ai eu un plus complexe mais je m'en suis débarrassé parce que ça n'a pas marché. Le problème avec celui que je viens de dactylographier est qu'il ne retournera que les quantités pour les articles que l'utilisateur a déjà, mais je dois également sélectionner les articles que l'utilisateur n'a pas commandés et mettre leur quantité à 0 – Deniz

+0

@ PieterGeerkens Je veux dire 1 client avec un ID spécifié – Deniz

Répondre

2

Celui-ci a attiré mon intérêt alors j'ai écrit une application de console pour le faire.

Andomar a répondu quelques instants avant moi (+1). C'est ma solution indépendante mais très proche de la sienne et pas plus simple ...

class Program { 
    private class CustomerDto { 
     public int CustomerId { get; set; } 
     public string CustomerName { get; set; } 
    } 
    private class ItemDto { 
     public int ItemId { get; set; } 
     public string ItemName { get; set; } 
    } 
    private class OrderDto { 
     public int Id { get; set; } 
     public int ItemId { get; set; } 
     public int CustomerId { get; set; } 
     public int Quantity { get; set; } 
    } 
    private class CustomerOrderDto { 
     public int CustomerId { get; set; } 
     public int ItemId { get; set; } 
     public int TotalQuantity { get; set; } 
    } 

    static void Main(string[] args) { 
     List<CustomerDto> Customers = new List<CustomerDto>() { 
      new CustomerDto() { CustomerId = 1, CustomerName = "one"}, 
      new CustomerDto() { CustomerId = 2, CustomerName = "two"}, 
      new CustomerDto() { CustomerId = 3, CustomerName = "three"} 
     }; 
     List<ItemDto> Items = new List<ItemDto>() { 
      new ItemDto() { ItemId = 1, ItemName = "item one"}, 
      new ItemDto() { ItemId = 2, ItemName = "item two"}, 
      new ItemDto() { ItemId = 3, ItemName = "item three"} 
     }; 
     // customer1 has 2 orders for item 1, 0 for item 2 or 3 
     // customer2 has 1 order for item 2, 0 for item 1 or 3 
     // customer3 has 1 order for item 2, 1 order for item 3 and 0 for item 1 
     List<OrderDto> Orders = new List<OrderDto>() { 
      new OrderDto() { Id = 1, CustomerId = 1, ItemId = 1, Quantity = 3 }, 
      new OrderDto() { Id = 1, CustomerId = 1, ItemId = 1, Quantity = 5 }, 
      new OrderDto() { Id = 1, CustomerId = 3, ItemId = 2, Quantity = 5 }, 
      new OrderDto() { Id = 1, CustomerId = 3, ItemId = 3, Quantity = 5 }, 
      new OrderDto() { Id = 1, CustomerId = 2, ItemId = 2, Quantity = 5 } 
     }; 
     List<CustomerOrderDto> results = (from c in Customers 
              from i in Items 
              join o in Orders on 
              new { c.CustomerId, i.ItemId } equals 
              new { o.CustomerId, o.ItemId } into oj 
              from o in oj.DefaultIfEmpty() 
              let x = o ?? new OrderDto() { CustomerId = c.CustomerId, ItemId = i.ItemId, Quantity = 0 } 
              group x by new { x.CustomerId, x.ItemId } into g 
              select new CustomerOrderDto() { 
               CustomerId = g.Key.CustomerId, 
               ItemId = g.Key.ItemId, 
               TotalQuantity = g.Select(x => x.Quantity).Sum() 
              } 
             ).ToList(); 
     foreach (var result in results) { 
      Console.WriteLine("Customer {0} purchased {1} units of item {2}", 
       result.CustomerId, result.TotalQuantity, result.ItemId); 
     } 
     Console.ReadKey(true); 
    } 
} 
+0

+ 1 Utilisation intéressante de l'instruction let. Bon cas de test btw (j'ai construit un cas de test dans SQL Server et Linqpad) – Andomar

+0

vous êtes très intelligent :) j'essaie maintenant de comprendre la requête maintenant – Deniz

2

Dans SQL, cela est assez simple:

select c.name 
,  i.name 
,  isnull(sum(o.quantity),0) 
from customers c 
cross join 
     items i 
left join 
     orders o 
on  o.customerid = c.customerid 
     and o.itemid = o.itemid 
group by 
     c.name 
,  i.name   

Traduit à LINQ, cela devient:

from c in Customers 
from i in Items 
join o in Orders 
    on new { c.Customerid, i.Itemid } 
    equals new { o.Customerid, o.Itemid } 
    into o1 
from o2 in o1.DefaultIfEmpty() 
group o2.Quantity 
    by new { CustomerName = c.Name, ItemName = i.Name } 
    into q 
select new { 
    q.Key.CustomerName, 
    q.Key.ItemName, 
    Quantity = q.Sum() ?? 0 
} 

J'espère que quelqu'un signale une version LINQ plus simple, parce que cela semble incroyablement complexe :)

+0

ouais, je m'attendais à ce que ce soit plus simple aussi ... – Tahbaza

1

Linq

from t in Customers 
join t2 in Orders on t.CustomerId equals (int)t2.CustomerId into t2Join 
from t2 in t2Join.DefaultIfEmpty() 
group t by t into t_g 
select new 
     { 
     CustomerId = t_g.Key.CustomerId, 
     OrdersId = t_g.Key.OrdersId, 
     Quantity = t_g.Key.Orders.Where(c => c.CustomerId == t_g.Key.CustomerId) 
           .Sum(c => c.Quantity) 
     }; 

Ceci n'est pas testé mais vous pouvez essayer.

2

Le LINQ expresssion

from c in Customers 
from i in Items 
select ... 

est un cross join de tous les clients et articles. La seule chose à faire est de résumer les quantités pour chaque:

var result = from c in Customers 
      from i in Items 
      select new 
      { 
       Customer = c, 
       Item = i, 
       Quantity = (from o in Orders 
          where o.CustomerId == c.CustomerId && o.ItemId == i.ItemId 
          select o.Quantity).Sum(), 
      }; 

Notez que Sum renvoie 0 pour un vide IEnumerable<int> (à savoir pas d'ordre trouvé).