C# 涉及Max()的SQL到LINQ转换
我想检索具有最新订单和总金额的前5名商户。然而,我似乎无法得到总金额。我认为问题在于C# 涉及Max()的SQL到LINQ转换,c#,mysql,entity-framework,linq,C#,Mysql,Entity Framework,Linq,我想检索具有最新订单和总金额的前5名商户。然而,我似乎无法得到总金额。我认为问题在于LastOrderGrandTotal=x.FirstOrDefault().GrandTotal。下面的代码语法是LINQ方法语法 var list = _ApplicationDbContext.OrderTransaction .Where(x => x.Status != 0) .GroupBy(x => x.MerchantUserId)
LastOrderGrandTotal=x.FirstOrDefault().GrandTotal
。下面的代码语法是LINQ方法语法
var list = _ApplicationDbContext.OrderTransaction
.Where(x => x.Status != 0)
.GroupBy(x => x.MerchantUserId)
.Select(x => new DashboardActiveMerchantStore { MerchantUserId = x.Key, CreatedDate = x.Max(c => c.CreatedDate), LastOrderGrandTotal= x.FirstOrDefault().GrandTotal })
.OrderByDescending(x => x.CreatedDate)
.Take(5)
.ToList();
为了进一步澄清,上面查询的SQL语法是
select TOP(5) MerchantUserId,MAX(CreatedDate),GrandTotal from OrderTransaction
group by MerchantUserId
order by CreatedDate desc
我有一个类来存储从LINQ语法检索的数据
public class DashboardActiveMerchantStore
{
public string MerchantName { get; set; }
public double LastOrderGrandTotal { get; set; }
public Guid MerchantUserId { get; set; }
public DateTime CreatedDate { get; set; }
}
我会像这样重写查询。您甚至可能不需要
first或default
,因为使用GroupBy
我相信至少总会有一条记录
var result = data
.Where(x => x.Status != 0)
.GroupBy(x => x.MerchantUserId)
.Select(q => new
{
q.Key,
Orders = q.OrderByDescending(q => q.CreatedDate),
})
.Select(x => new DashboardActiveMerchantStore {
MerchantUserId = x.Key,
CreatedDate = x.Orders.FirstOrDefault().CreatedDate,
LastOrderGrandTotal = x.Orders.FirstOrDefault().GrandTotal,
})
.Take(5)
.ToList();
当您使用实体框架时,一种完全不同、更自然的方法是可能的。您可以使用
虚拟ICollection
我想检索具有最新订单和总金额的前5名商户
实体框架中的类
似乎商户
和订单交易
之间存在一对多的关系:每个商户都有零个或多个订单交易,并且每个订单交易都是一个确切的何时商户的交易,即外键机制所指的商户
如果您遵循了,您将拥有类似于以下内容的类:
public class Merchant
{
public Guid Id {get; set;} // primary key
public string Name {get; set;}
...
// Every Merchant has zero or more TransactionOrders (one-to-many)
public virtual ICollection<TransactionOrder> TransactionOrders {get; set;}
}
public class TransactionOrder
{
public Guid Id {get; set;} // primary key
public DateTime CreatedDate {get; set;}
public int Status {get; set;}
public double GrandTotal {get; set;}
...
// every TransactionOrder is an order of a Merchant, using foreign key
public Guid MerchantId {get; set;}
public virtual Merchant Merchant {get; set;}
}
实体框架知道您的一对多关系。由于您使用的是虚拟ICollection
,因此它将自动为您创建(组)加入
现在你不需要所有的商人,你不需要没有LastOrder的商人。他们没有任何非零状态的订单。从剩余的商户中,您只需要具有最新LastOrder.CreatedDate的五家商户
因此,删除所有没有LastOrders的商家,按LastOrder.CreatedDate降序下单,并取前5名
继续LINQ:
.Where(merchant => merchant.LastOrder != null) // at leas one Order with non-zero Status
.OrderbyDescending(merchant => merchant.LastOrder.CreatedDate)
.Take(5).
您将有“商家(Id和名称)及其最近的订单(CreatedData和GrandTotal)”,如果需要,请添加一个额外的选择,将其转换为五个
仪表板ActiveMerchantstores
我认为x.FirstOrDefault()
不是同一个,因为您在调用它之后正在对列表进行排序。你最安全的选择是保留整个列表,进行排序,然后在排序后选择。但我不认为我们可以在保留整个列表之后进行排序。因为列表包含重复条目,我希望它按商户分组。我最初的计划是根据创建的数据按商户订单分组并获取总计,但我似乎无法根据您的SQL查询访问总计,它应该是LastOrderGrandTotal=x.GrandTotal
。但我不确定您的SQL查询如何正常工作。因为您有groupby onMerchantUserId
。因此,您只能在select中使用MerchantUserId
和聚合函数,而不能使用其他列。请检查SQL查询是否成功运行@Tanyijing认为SQL查询不可能工作;它将抛出…在选择列表中无效,因为它既不包含在聚合函数中,也不包含在groupby子句中
“With groupby始终存在记录”-即使我们将空列表分组?@CaiusJard则没有x
可供选择,因此您无需担心子集合中没有项目。因此,是的,空列表=无记录。
public class OrderDbContext : DbContext
{
public DbSet<Merchant> Merchants {get; set;}
public DbSet<TransactionOrder> TransactionOrders {get; set;}
}
var result = dbContext.Merchants
.Select(merchant => new
{
Id = merchant.Id,
Name = merchant.Name,
// from Every Merchant, get the Date and Total of their last
// non-zero status Order
// or null if there is no such order at all
LastOrder = merchant.OrderTransactions
.Where(orderTransaction => orderTransaction.Status != 0)
.OrderByDescending(orderTransaction => oderTransaction.CreatedDate)
.Select(orderTransaction => new
{
CreatedDate = orderTransaction.CreatedDate,
GrandTotal = orderTransaction.GrandTotal,
})
.FirstOrDefault(),
})
.Where(merchant => merchant.LastOrder != null) // at leas one Order with non-zero Status
.OrderbyDescending(merchant => merchant.LastOrder.CreatedDate)
.Take(5).