如何将Group By SQL转换为LINQ?

时间:2015-10-05 20:10:50

标签: c# entity-framework linq linq-to-sql linq-to-entities

我有以下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)

我已经在LINQ中使用Group By以及子查询进行了一些搜索。我正在使用带有“C#语句”的LinqPad,我想出了以下内容,基于一些示例,我发现它看起来应该可行。但是,我在尝试将esn.S_NUMBER分配给匿名对象中的sNumber时遇到错误。消息说'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();

我的印象是所有记录基本上都会放入一个名为esn的临时表中,我可以调用temptable.column名称将其分配给我最终将作为列表返回的对象。

2 个答案:

答案 0 :(得分:4)

您想使用Key代替S_NUMBER。分组时,结果会被放入IEnumerable<IGrouping>>。分组具有Key属性,该属性保存该组的密钥,在这种情况下,它是您的S_NUMBER

select new
{
    sNumber = esn.Key
};

以下查询应该是原始SQL查询的翻译。我们不是使用子查询,而是将另一个 from...in分组并“整理”序列,并检查每个分组是否与原始查询一样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
             };

答案 1 :(得分:1)

由于您使用一个查询的结果来过滤另一个查询,我们可以像这样对查询进行相当直接的音译:

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 };

它不仅看起来更像原始查询,而且它应该比在LINQ中可能更简单的另一种形式执行得更快(至少在MS SQL上,不能为其他人说话)转换为SQL时要复杂得多......在我的测试版本中,有四个选择和一个交叉连接,两个选择和一个内部连接。

当然,如果您愿意,为了清晰起见,您可以将内部查询作为单独的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 };