使用Linq为每位客户带回最后3,4 ...... n个订单

时间:2011-04-05 04:56:57

标签: linq entity-framework lambda

我有一个包含客户订单的数据库。 我想使用Linq(到EF)来查询数据库,以便为每个客户带回最后(最近的)3,4 ... n个订单。

注意: 客户1可能在最后一小时内刚刚订购了12个订单;但自上周以来,客户2可能没有提供任何产品。

我不能为我的生活找出如何在linq(lambda表达式)中编写查询以获取数据集。

有什么好主意吗?

修改 客户和订单是一种简化。我查询的表实际上是各种Web服务的出站消息记录。将客户和订单描述为更加容易。关系是一样的。 我正在构建一个任务,检查每个Web服务的最后n条消息,看看是否有任何故障。我们想要一个Web服务的半实时健康状态。

@CoreySunwold
我的表看起来有点像这样:
MessageID,WebserviceID,SentTime,状态,消息,错误,

或者来自客户/订单上下文,如果它更容易:
OrderID,CustomerID,StatusChangedDate,状态,WidgetName,评论

编辑2: 我最终找到了一些东西 (帽子小贴士给@StephenChung,基本上提出了完全相同的,但在经典的linq)

var q = myTable.Where(d => d.EndTime > DateTime.Now.AddDays(-1))
.GroupBy(g => g.ConfigID)
.Select(g =>new { ConfigID = g.Key, Data = g.OrderByDescending(d => d.EndTime) .Take(3).Select(s => new { s.Status, s.SentTime }) }).ToList();

执行需要一段时间。所以我不确定这是否是最有效的表达方式。

6 个答案:

答案 0 :(得分:2)

您可以将SelectMany用于此目的:

customers.SelectMany(x=>x.orders.OrderByDescending(y=>y.Date).Take(n)).ToList();

答案 1 :(得分:2)

这应该给出每个客户的最后3个订单(如果有订单的话):

from o in db.Orders
group o by o.CustomerID into g
select new {
  CustomerID=g.Key,
  LastOrders=g.OrderByDescending(o => o.TimeEntered).Take(3).ToList()
}

但是,我怀疑这会强制数据库返回整个 Orders表,然后为每个客户挑选最后3个。检查生成的SQL。

如果需要优化,则必须手动构建一个SQL,只返回最后一个,然后将其转换为视图。

答案 2 :(得分:0)

这个怎么样?我知道它适用于常规收藏但不了解EF。

yourCollection.OrderByDescending(item=>item.Date).Take(n);

答案 3 :(得分:0)

var orders = orders.Where(x => x.CustomerID == 1).OrderByDescending(x=>x.Date).Take(4);

这将需要最后4个订单。具体查询取决于您的表/实体结构。

顺便说一下:您可以将x作为订单。所以你可以这样读取:获取订单,其中order.CustomerID等于1,OrderThem by order.Date并取前4行'。

答案 4 :(得分:0)

var ordersByCustomer = 
db.Customers.Select(c=>c.Orders.OrderByDescending(o=>o.OrderID).Take(n));

这将返回按客户分组的订单。

答案 5 :(得分:-1)

有人可能会在这里纠正我,但我认为这样做是linq,单个查询可能非常困难,如果不是不可能的话。我会使用商店程序和类似的东西

select 
    *
    ,RANK() OVER  (PARTITION BY c.id ORDER BY o.order_time DESC) AS 'RANK'
from 
    customers c 
inner join 
    order o
on 
    o.cust_id = c.id
where 
    RANK < 10 -- this is "n"

我暂时没有使用这种语法,所以它可能不太正确,但如果我理解了这个问题,那么我认为这是最好的方法。