linq - 使用 LINQ 选择子查询的 SUM()
问题描述
我正在尝试学习如何使用 LINQ 执行产生与此相同结果的查询:
SELECT (
SELECT SUM(point)
FROM communitymemberpointfeature
WHERE communitymemberpointfeature.communitymemberid = communitymember.id
) AS points, communitymember.*
FROM communitymember
在网上浏览了一下之后,我构造了以下语句:
var list = (from pointFeature in communityMemberPointFeatureList
join member in communityMemberList on pointFeature.CommunityMemberId equals member.Id
group pointFeature by new { pointFeature.CommunityMemberId }
into grouping
select new
{
grouping,
points = grouping.Sum(row => row.Point)
}).ToList();
但这产生了类似的结果
[
{
points:7200,
grouping:[
{Id:1,Point:5000,FeatureId:1,CommunityMemberId:1},
{Id:2,Point:2200,FeatureId:1,CommunityMemberId:1},
],
}
...
]
我真正想要的是一个结果集,例如:
[
{points:7200,CommunityMemberId:1,firstname:'john',lastname:'blah' ....},
...
]
有人可以告诉我我做错了什么吗?
解决方案
将评论添加到末尾后编辑
我可以想象您在将 SQL 转换为 LINQ 时遇到问题。在尝试编写 LINQ 语句时,从您的需求开始通常比从 SQL 语句开始要容易得多。
在我看来,您与 CommunityMembers 有一张桌子。每个 CommunityMember 在属性 Id 中都有一个主键。
此外,每个 CommunityMember 都有零个或多个 CommunityMemberPointFeatures,即那些具有外键 CommunityMemberId 的 CommunityMemberPointFeatures,该外键等于它所属的 CommunityMember 的主键。
例如:CommunityMember [14] 的所有 CommunityMemberPointFeatures 的 CommunityMemberId 值都等于 14。
要求
如果我查看您的 SQL,在我看来,您想查询所有 CommunityMember,每个 CommunityMember 的所有 CommunityMemberPointFeatures 的属性 Point 的总和。
每当您要查询“带有零个或多个子项的项目”时,例如“学校及其学生”、“客户及其订单”、“社区成员及其 PointFeatures”,请考虑使用GroupJoin。
GroupJoin 实际上是一个左外连接,后跟一个 GroupBy 以将左项与其所有右项组成组。
var result = dbContext.CommunityMembers // GroupJoin CommunityMembers
.GroupJoin(CommunityMemberPointFeatures, // With CommunityMemberPointFeatures
communityMember => communityMember.Id, // from every CommunityMember take the Id
pointFeature => pointFeature.CommunityMemberId, // from every CommunityMemberPointFeature
// take the CommunityMemberId
// Parameter ResultSelector: take every CommunityMember, with all its matching
// CommunityMemberPointFeatures to make one new object:
(communityMember, pointFeaturesOfThisCommunityMember) => new
{
// Select the communityMember properties that you plan to use:
Id = communityMember.Id,
Name = communityMember.Name,
...
// From the point features of this CommunityMember you only want the sum
// or property Point:
Points = pointFeaturesOfThisCommunityMember
.Select(pointFeature => pointFeature.Point)
.Sum(),
// However, if you want more fields, you can use:
PointFeatures = pointFeaturesOfThisCommunityMember.Select(pointFeature => new
{
Id = pointFeature.Id,
Name = pointFeature.Name,
...
// not needed, you know the value:
// CommunityMemberId = pointFeature.CommunityMemberId,
})
.ToList(),
});
评论后编辑
如果需要,您可以省略选择您计划使用的值。
// Parameter ResultSelector:
(communityMember, pointFeaturesOfThisCommunityMember) => new
{
CommunityMember = communityMember,
PointFeatures = pointFeaturesOfThisCommunityMember.ToList(),
),
但是,我强烈建议不要这样做。如果 CommunityMember [14] 有一千个 PointFeature,那么每个 PointFeature 都会有一个值为 14 的外键。因此,您将传输该值 14 1001 次。多么浪费处理能力,更不用说您计划不使用的所有其他字段。
此外:如果你这样做,你就违反了信息隐藏:每当你的表在内部发生变化时,这个函数的结果就会改变。那是你要的吗?
推荐阅读
- javascript - jquery .then 不会抛出错误
- azure-servicebus-queues - 是否有 Azure 服务总线消息过期事件
- flutter - 发生异常。NoSuchMethodError Flutter 验证错误
- cordova - 是否可以将网站包装在cordova应用程序中,但保持服务器会话并在底部添加固定栏菜单?
- node.js - 如何为 ExpressJS 路由保持 Nginx 上游?
- mysql - current_timestamp 错误对应于您的 MariaDB 服务器版本
- windows - Windows、Git 和裸存储库的 SSH url/路径
- selenium - 在无头和普通 chrome 之间弹出不同的 Google 登录
- powershell - Powershell脚本查看计算机是否设置为进入睡眠状态或显示器已关闭?
- angular - onSubmit 在 Angular 中触发两次