我想将以下 SQL 转换为 LINQ:
select count(p.ID) as NumPosts,
count(t.Trustee_ID)as TrusteePost,
count(pat.ID)as PatientPost,
count(s.ID) as SpecialistPost
from [dbo].[Posts] as p
left join [dbo].[Trusteehips] as t
on p.Autor_ID = t.Trustee_ID
left join [dbo].[Patients] as pat
on p.Autor_ID = pat.ID
left join [dbo].[Specialists] as s
on p.Autor_ID = s.ID
where p.Deleted = 0
我已经尝试过这个:
var res = from p in context.Posts
join t in context.Trusteeships
on p.Autor.ID equals t.Trustee.ID into tGroup
join pat in context.Patients
on p.Autor.ID equals pat.ID into patGroup
join s in context.Specialists
on p.Autor.ID equals s.ID into sGroup
select new NumUserPosts
{
//CountAllPosts = ?
TrusteePost = tGroup.Count(),
PatientPost = patGroup.Count(),
SpecialistPost = sGroup.Count()
};
但结果是这样的:
1 0 0
0 0 1
0 0 1
0 1 0
and etc.
我期待结果
TrusteePost PatientPost SpecialistPost
1000 2000 3000
为什么当我尝试计算组时返回此结果? SQL查询正确。我想翻译成LINQ。
最佳答案
查询返回每个加入的 Trustee
等 0 或 1 条记录,因为您通过唯一主键进行外部联接。因此,join into
(在流畅语法中是 GroupJoin
)会生成一组 0 或 1 条记录。如果您运行生成的 SQL 查询并查看原始查询结果,您可能会更好地了解发生了什么。
问题是,count(t.Trustee_ID)
等没有 LINQ 等效项。因此,如果不进行“黑客攻击”,就不可能在一个查询中完成您想要的操作。
将其破解为一个查询可以像这样完成:
(from p in context.Posts.Take(1)
select new
{
TrusteePost = context.Posts
.Count(p1 => context.Trusteeships.Any(x => x.ID == p1.Autor.ID)),
PatientPost = context.Posts
.Count(p2 => context.Patients.Any(x => x.ID == p2.Autor.ID)),
SpecialistPost = context.Posts
.Count(p3 => context.Specialists.Any(x => x.ID == p3.Autor.ID))
})
.AsEnumerable()
.Select(x => new NumUserPosts
{
CountAllPosts = x.TrusteePost + x.PatientPost + x.SpecialistPost,
x.TrusteePost,
x.PatientPost,
x.SpecialistPost
}
SQL 查询将比原始 SQL 更加复杂(例如,它涉及交叉联接),但它可能仍然会执行得很好。 AsEnumerable
阻止第二部分作为 SQL 执行,这会使 SQL 语句更加臃肿。它只是在内存中运行。
我认为这是一个黑客行为,因为第一部分 context.Posts.Take(1)
实际上没有任何意义,它只是充当三个单独查询的包装器。这是穷人的查询包装。
关于sql - 为什么 LINQ Count() 返回多行而不是一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29790199/