[英]How to convert Group By SQL to LINQ?
I have the following SQL statement I'm trying to convert to Entity Framework. 我尝试将以下SQL语句转换为Entity Framework。
SELECT S_NUMBER,A_NUMBER,FIRST_NAME,LAST_NAME
FROM EMPLOYEE WHERE S_NUMBER IN (
SELECT S_NUMBER
FROM EMPLOYEE
WHERE CO='ABC'
GROUP BY S_NUMBER
HAVING COUNT(*) > 1)
I've done some searching on using Group By in LINQ as well as sub-queries. 我已经在LINQ中使用Group By以及子查询进行了一些搜索。 I'm using LinqPad with a "C# Statement" and I came up with the following which based on some examples I found looks like it should work.
我使用带有“ C#语句”的LinqPad,并根据以下发现的示例得出了以下结论: However, I'm getting errors when trying to assign esn.S_NUMBER to sNumber in the anonymous object.
但是,尝试将esn.S_NUMBER分配给匿名对象中的sNumber时出现错误。 The message says 'IGrouping' does not contain a definition for 'S_NUMBER'.
消息显示“ IGrouping”不包含“ S_NUMBER”的定义。
var result = from e in EMPLOYEE
where e.CO=="ABC"
group e by e.S_NUMBER into esn
select new
{
sNumber = esn.S_NUMBER
};
result.Dump();
I was under the impression that all the records would basically get put into a temp table called esn and I could be able to call the temptable.column name to assign it to my object that I will eventually return as a list. 我的印象是,所有记录基本上都将放入一个名为esn的临时表中,我可以调用temptable.column名称将其分配给我的对象,最终我将以列表形式返回该对象。
You want to use Key
instead of S_NUMBER
. 您想使用
Key
而不是S_NUMBER
。 When grouping, the results get put into a IEnumerable<IGrouping>>
. 分组时,结果放入
IEnumerable<IGrouping>>
。 The grouping has a Key
property which holds the key for that group, which in this case it's your S_NUMBER
. 分组具有
Key
属性,该属性保存该组的密钥,在本例中为您的S_NUMBER
。
select new
{
sNumber = esn.Key
};
The following query should be a translation of the original SQL query. 以下查询应为原始SQL查询的翻译。 Instead of using a subquery, we're grouping and doing another
from...in
to "flatten" the sequence, and also checking that each grouping has a count > 1
like the original query. 而不是使用子查询,我们将分组并
from...in
进行另一个操作以“拉平”序列,并检查每个分组是否像原始查询一样具有count > 1
的count > 1
。
var result = from e in EMPLOYEE
where e.CO=="ABC"
group e by e.S_NUMBER into esn
from e2 in esn
where esn.Count() > 1
select new
{
e.S_NUMBER,
e.A_NUMBER,
e.FIRST_NAME,
e.LAST_NAME
};
Since you're using the results of one query to filter another we can do a fairly direct transliteration of the query like so: 由于您使用的是一个查询的结果来过滤另一个查询的结果,因此我们可以对查询进行相当直接的音译,如下所示:
var result =
from e in EMPLOYEE
join f in (
from fe in EMPLOYEE
where fe.CO == 'ABC'
group null by S_NUMBER into grp
where grp.Count() > 1
select grp.Key
)
on e.S_NUMBER equals f
select new { e.S_NUMBER, e.A_NUMBER, e.FIRST_NAME, e.LAST_NAME };
Not only does this look a lot more like the original query but it should perform a bit faster (on MS SQL at least, can't speak for others) than the other form that might be simpler in LINQ but is much more complex when converted to SQL... four selects and a cross join, in my test version, vs two selects and an inner join for this one. 这不仅看起来更像原始查询,而且它的执行速度(至少在MS SQL上,不能代表其他人)要比LINQ中可能更简单但转换时要复杂得多的其他形式要快一些。到SQL ...在我的测试版本中,有四个选择和一个交叉联接,而与此相比,两个选择和一个内部联接。
Of course if you prefer you can pull the inner query out as a separate IQueryable
for clarity: 当然,如果您愿意,可以将内部查询作为单独的
IQueryable
进行拉出,以进行清楚说明:
var filter =
from e in EMPLOYEE
where e.CO == 'ABC'
group null by S_NUMBER into grp
where grp.Count() > 1
select grp.Key;
var result =
from e in EMPLOYEE
join f in filter
on e.S_NUMBER equals f
select new { e.S_NUMBER, e.A_NUMBER, e.FIRST_NAME, e.LAST_NAME };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.