C# linq中的Group by和left join
有两个表,一个是customers有字段C# linq中的Group by和left join,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,有两个表,一个是customers有字段customerID,GroupID,另一个是CustomerGroup有字段GroupID,GroupName,我想得到每个组中customerID的数量,下面是LINQ语句: var groups = from customerGroups in db.CustomerGroup join customers in db.Customers on customerGroups.GroupID equa
customerID
,GroupID
,另一个是CustomerGroup
有字段GroupID
,GroupName
,我想得到每个组中customerID
的数量,下面是LINQ语句:
var groups = from customerGroups in db.CustomerGroup
join customers in db.Customers on customerGroups.GroupID equals customers.GroupID into gc
where customerGroups.MerchantID == merchantID
from subCustomerGroups in gc.DefaultIfEmpty()
group customerGroups by customerGroups.GroupName into grpCustomerGroups
select new { GroupName = grpCustomerGroups.Key, Quantity = customers.Count()};
问题是Quantity=customers.Count()
无效,如何更正该语句?
预期的sql语句是
exec sp_executesql N'SELECT
1 AS [C1],
[GroupBy1].[K1] AS [GroupName],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[GroupName] AS [K1],
COUNT(CustomerID) AS [A1]
FROM [dbo].[CustomerGroup] AS [Extent1]
LEFT OUTER JOIN [dbo].[Customer] AS [Extent2] ON [Extent1].[GroupID] = [Extent2].[GroupID]
WHERE [Extent1].[MerchantID] = @p__linq__0
GROUP BY [Extent1].[GroupName]
) AS [GroupBy1]',N'@p__linq__0 bigint',@p__linq__0=9
通常,如果你发现自己做了一个左外连接,后面跟着一个分组,那是因为你想要“带有他们的子项目的项目”,比如“带学生的学校”,“有订单的客户”,“CustomerGroups和他们的客户”等等。如果你想要这个,考虑使用而不是“加入+默认的+GROPBY”< /P>。 我更熟悉方法语法,所以我将使用该语法
int merchantId = ...
var result = dbContext.CustomerGroups
// keep only the CustomerGroups from merchantId
.Where(customerGroup => customerGroup.MerchantId == merchantId)
.GroupJoin(dbContext.Customers, // GroupJoin with Customers
customerGroup => customerGroup.GroupId, // from every CustomerGroup take the GroupId
customer => customer.GroupId, // from every Customer take the GroupId
// ResultSelector:
(customerGroup, customersInThisGroup) => new // from every CustomerGroup with all its
{ // matching customers make one new object
GroupName = customerGroup.Key,
Quantity = customersInThisGroup.CustomerId, // ???
});
简言之:
以CustomerGroup的序列为例。仅保留那些属性MerchantId的值等于MerchantId的CustomerGroup。通过比较CustomerGroup.GroupId与每个Customer.GroupId,从剩余的每个CustomerGroup中获取其所有客户
结果是一系列CustomerGroup,每个都有自己的客户。从该结果(参数ResultSelector)获取来自客户的GroupName和来自该组中客户的数量
你的声明是:
Quantity = customers.CustomerID,
这是行不通的。我肯定这不是你想要的。唉,你忘了写你想要的东西。我认为是这样的:
Quantity = customers.Count().
但如果您想要此CustomerGroup中所有客户的CustomerId:
// ResultSelector:
(customerGroup, customersInThisGroup) => new
{
GroupName = customerGroup.Key,
CustomerIds = customersInThisGroup.Select(customer => customer.CustomerId)
.ToList(),
);
如果需要,您可以使用ResultSelector获取“CustomerGroup with the Customers”。最有效的方法是仅选择实际计划使用的属性:
// ResultSelector:
(customerGroup, customersInThisGroup) => new
{
// select only the CustomerGroup properties that you plan to use:
Id = CustomerGroup.GroupId,
Name = CustomerGroup.Name,
... // other properties that you plan to use
Customers = customersInThisGroup.Select(customer => new
{
// again, select only the Customer properties that you plan to use
Id = customer.Id,
Name = customer.Name,
...
// not needed, you know the value:
// GroupId = customer.GroupId
});
不选择客户的外键的原因是效率。如果CustomerGroup[14]有1000个客户,则此组中的每个客户的GroupId值都将等于[14]。发送此值[14]1001次将是一种浪费。根据您的回答,我做了一个小改动,它对我有效!(customerGroup,customersInThisGroup)=>新建//从每个customerGroup及其所有{//匹配的客户创建一个新对象GroupID=customerGroup.GroupID,GroupName=customerGroup.GroupName,Quantity=customersInThisGroup.Count(),});