【问题标题】:SQL to C# LINQ query with multiple group by inner queries and having clausesSQL to C# LINQ 查询具有多个按内部查询分组并具有子句
【发布时间】:2018-06-14 01:24:03
【问题描述】:

我有一个包含一组值的列表。我想使用c# 中的LINQ 查询来检查表是否具有匹配计数的匹配值

这是我的清单:

List<int> list1 = new List<int>()
        {
          130011,
          130010
        };

这是我的桌子

RelEmployeeDepartments:

ID  EmpID DeptID
8   4     130011
9   4     130010
10  4     2
18  13    130011
19  13    130010
20  13    1
21  13    2
23  5     130011
24  5     130010

现在我想找到所有已分配到确切部门的所有员工list1 具有相同的计数。因此,对于我的list1 中的值,输出应为EmpID 5,因为它具有相同的值和相同的部门数。 EmpID 4 & 13 不应该出现在我的输出中,因为即使员工有匹配的部门,计数也不同。

这是我想出的有效 SQL 查询:

SELECT EmpID FROM 
RelEmployeeDepartments WHERE EmpID IN 
(SELECT red.EmpID FROM RelEmployeeDepartments red
GROUP BY red.EmpID HAVING COUNT(red.DeptID) = 2)
AND DeptID IN (130010,130011) 
GROUP BY EmpID HAVING COUNT(DeptID) = 2

我设法像这样使用LINQ 获得内部查询,但无法完全转换它。

var innerQuery = (from red in RelEmployeeDepartments 
                           group red by red.EmpID into red1
                           where red1.Count().Equals(list1.length)
                           select red1.Key);

我想知道如何将其转换为 LINQ 查询,或者是否有比上述更好的解决方案?

【问题讨论】:

    标签: c# sql-server linq


    【解决方案1】:

    您可以使用ContainGroupByWhere 子句的组合:

    var result = RelEmployeeDepartments
                     .Where(e => list1.Contains(e.DeptID))
                     .GroupBy(g => g.EmpId)
                     .Where(grp => grp.Count() == list1.Count())
    

    上面会给你IGrouping,然后你可以SelectSelectMany得到IEnumerable&lt;int&gt;EmpID

    result.Select(grp => grp.Select(v => v.EmpId)).SelectMany(x => x).Distinct()
    

    【讨论】:

    • 这也给了我 4,5 和 13,因为输出只需要 5
    • 你知道它是因为.Where(...Contains... 失败还是.Where(...Count... 失败而返回所有三个数字吗?
    • 无论我看到什么,这都是计数形式的问题。这是我使用 LINQPad 从您的 LINQ 查询中得到的 sql 查询: DECLARE p0 Int = 130010 DECLARE p1 Int = 130011 DECLARE p2 Int = 2 -- EndRegion SELECT DISTINCT [t2].[EmpID] FROM ( SELECT COUNT(*) AS [ value], [t0].[EmpID] FROM [RelEmployeeDepartments] AS [t0] WHERE [t0].[DeptID] IN (p0, p1) GROUP BY [t0].[EmpID] ) AS [t1] CROSS JOIN [RelEmployeeDepartments ] AS [t2] WHERE ([t1].[value] = p2) AND ([t1].[EmpID] = [t2].[EmpID]) AND ([t2].[DeptID] IN (p0, p1) );删除了 @ 变量,因为 stackoverflow 不允许。
    • 这很奇怪,这里是another answer 建议相同的解决方案。也许试试那个符号?
    • 这样我得到了一半,只需要在某个地方放置一个包含查询。你能看看吗?从 RelEmployeeDepartments 组中的 red 按 red.EmpID 变为 red1 其中 red1.Count().Equals(list1.length) 选择 red1.Key
    【解决方案2】:

    最后经过大量的努力,帮助@farzan-mirheydari 回答和Using linq to group a table that contains substrings 这是我的工作解决方案。这是我在问题中的 SQL 查询的精确转换

    from red1 in RelEmployeeDepartments
    where
     (from red in RelEmployeeDepartments group red by new {
       red.EmpID
      }
      into g where g.Count() == list1.Count() select new {
       g.Key.EmpID
      }).Contains(new {
      EmpID = red1.EmpID
     }) &&
     (list1).Contains(red1.DeptID)
    group red1 by new {
     red1.EmpID
    }
    into g
    where g.Count() == list1.Count()
    select new {
     g.Key.EmpID
    };
    

    Lambda 代码:

        RelEmployeeDepartments
       .Where(
        red1 =>
        (RelEmployeeDepartments
         .GroupBy(
          red =>
          new {
           EmpID = red.EmpID
          }
         )
         .Where(g => (g.Count() == list1.Count()))
         .Select(
          g =>
          new {
           EmpID = g.Key.EmpID
          }
         )
         .Contains(
          new {
           EmpID = red1.EmpID
          }
         ) &&
         list1.Contains(red1.DeptID)
        )
       )
       .GroupBy(
        red1 =>
        new {
         EmpID = red1.EmpID
        }
       )
       .Where(g => (g.Count() == list1.Count()))
       .Select(
        g =>
        new {
         EmpID = g.Key.EmpID
        }
       );
    

    我知道它看起来很复杂。如果有更好或更简单的方法,请发布。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-12
      相关资源
      最近更新 更多