【问题标题】:How to make a LINQ query for this?如何为此进行 LINQ 查询?
【发布时间】:2013-02-17 07:12:57
【问题描述】:

好的,现在卡了一天,请有人帮忙!

我想选择特定客户拥有的所有可能物品的数量,无论他们是否订购了该物品。因此,如果他们没有订购它(即它不在 Orders 表中),则为数量返回 0 值。

订单 CustomerId ItemId 数量

项目 物品编号 物品名称

客户 客户编号 客户姓名

我猜这将涉及某种子查询,但真的不确定。

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

【问题讨论】:

  • 我不理解您所说的“特定客户拥有”的意思。客户如何“拥有”一件商品?
  • @TimSchmelter 已更新。我确实有一个更复杂的,但因为它不起作用而摆脱了它。我刚刚输入的问题是它只会返回用户已经拥有的商品的数量,但我还需要选择用户尚未订购的商品并将其数量设置为 0跨度>
  • @PieterGeerkens 我的意思是 1 个具有指定 ID 的客户
  • @TimSchmelter 我指的是最终的客户,而不是用户!大声笑

标签: c# linq


【解决方案1】:

在 SQL 中,这很简单:

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        

翻译成 LINQ,变成:

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 
}

我希望其他人发布一个更简单的 LINQ 版本,因为这看起来非常复杂 :)

【讨论】:

    【解决方案2】:

    灵巧

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

    这个没有测试,但是你可以试试。

    【讨论】:

      【解决方案3】:

      这个引起了我的兴趣,所以我写了一个控制台应用来做。

      安多马尔在我回答之前(+1)回答了我。 这是我的独立解决方案,但非常接近他的,并不简单......

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

      【讨论】:

      • +1 let 语句的有趣用法。不错的测试用例顺便说一句(我在 SQL Server 和 Linqpad 中构建了一个测试用例)
      • 你们很聪明 :) 我现在正在尝试理解查询
      【解决方案4】:

      LINQ 表达式

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

      是所有客户和项目的cross join。所以剩下要做的就是总结每个的数量:

      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(),
                   };
      

      请注意,Sum 为空的IEnumerable&lt;int&gt; 返回 0(即未找到订单)。

      【讨论】:

        猜你喜欢
        • 2020-05-21
        • 1970-01-01
        • 2021-01-15
        • 1970-01-01
        • 1970-01-01
        • 2019-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多