使用LINQ进行GROUP BY和HAVING COUNT

6

我希望了解我的 Linq 中的 GROUP BY 查询出了什么问题。我尝试了许多示例(例如Linq with group by having count),但我仍然会得到更多结果(好像 WHERE 被跳过了一样)。我的代码如下:

var test = session.Query<SomeClass>()
                  .GroupBy(c => new { c.Var1, c.Var2, c.Var3 })
                  .Where(g => g.Count() > 1)
                  .Select(g => g.Key.Var3)
                  .ToList();

这里有229个结果(所有记录)。我想在Linq中构建的查询是:
SELECT Var3
FROM myTable
GROUP BY Var1, Var2, Var3
HAVING COUNT(*) > 1

一些方式,查询给我返回了27个结果,但是Linq表达式给了我229个结果(所有)。当我将Linq表达式中的where/select部分替换为以下内容时,我确实得到了一个计数至少为2的列表:
.Select(g => new { Item = g.Key, Count = g.Count() })

但我不想要一个带有项目(和计数)的列表,并且必须遍历该列表,我希望在Linq表达式中使HAVING部分起作用...
编辑2:如果您查看LINQ Group By Multiple fields -Syntax help,这对我也有效。 但是,我将获得具有Var1、Var2、Var3和Count的对象列表。 在此列表中,我只想要具有Count大于1的对象的Var3。
有谁能指点我正确的方向吗?
编辑1:正如我在介绍中所说,问题Linq with group by having count并没有回答我的问题。 如果我使用此代码,则仍然会有229个结果集,而实际上“重复”的结果只有27个(即,在分组后计数超过1)。
编辑3:我目前正在使用以下内容。我需要两个语句,我认为这很奇怪,但正如之前所述,这似乎是仅选择记录计数> 1的唯一方法。
var querygroup = session.Query<SomeClass>()
                        .GroupBy(e => new { e.Var1, e.Var2, e.Var3 })
                        .Select(s => new { s.Key.Var1, s.Key.Var2, s.Key.Var3, Count = s.Count() })
                        .ToList();

var duplicates = querygroup.Where(g => g.Count > 1)
                           .Select(g => new SomeClass() { Var1 = g.Var1, Var2 = g.Var2, Var3 = g.Var3})
                           .ToList();

请注意,我决定选择Var1和Var2的值,并将它们存储在SomeClass()中,而不是仅选择Var3。这只是一个补充,选择所有内容并不能帮助创建一个语句来获取此选择。
编辑4:当然,我可以将duplicates变量中的.Where..部分添加到querygroup语句中,从而使整个语句成为一个。成功了吗?似乎有点过度设计,但至少它能工作。
如果有人能找出我为什么需要两个语句,请详细说明 :)

可能是Linq with group by having count的重复问题。 - Pieter Geerkens
1
为了确定问题是否出在翻译后的 SQL 查询上,请尝试运行以下代码:var testA = session.Query<SomeClass>().GroupBy(c => new { c.Var1, c.Var2, c.Var3 }).ToList(); var test = testA.Where(g => g.Count() > 1).Select(g => g.Key.Var3).ToList();,并查看结果。 - Ivan Stoev
@IvanStoev,这里出现了一个查询错误,因为“id”列不是GROUP语句的一部分,所以需要添加一个SELECT。 - Tjab
@Tjab,使用帖子中的原始查询。将 ToList() 替换为 ToString()。你看到了类似 SQL 的东西吗? - Ivan Stoev
2
啊,原来既不是LINQ to SQL也不是EF,而是NHibernate。这样的事很重要,你应该正确地标记问题,因为每个ORM映射器都有其特定之处(和错误)。在这里我们不能再做更多了,祝好运。 - Ivan Stoev
显示剩余7条评论
3个回答

1

试试这个

var test = session.Query<SomeClass>()
                  .GroupBy(c => new { c.Var1, c.Var2, c.Var3 })
                  .Select(d=> new { var1 = d.Key.var1,var2 = d.Key.var2,var3=d.Key.var3,records = d.ToList()})
                  .Where(e => e.records.Count() > 1)
                  .Select(g => g.Var3)
                  .ToList();

我一开始很有希望,因为看起来差不多,但是记录太多了(非常确定它跳过了计数部分并选择了所有记录)。当我删除HAVING部分时,您的示例与SELECT Var3 FROM table GROUP BY Var1, Var2, Var3 HAVING COUNT(*) > 1具有相同的结果。 - Tjab
更好的是,在您的示例中,如果我将选择部分更改为.Select(g => g.records.Count()),我会得到一个包含229个(全部)记录的列表,类似于1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,5,1,1,1,1,1等(27次不是1)。我对此感到非常困惑,因为我只想选择不是1的记录... - Tjab
1
@Tjab,我已更新答案,请也尝试一下。我通过使用ToList来实现了记录的具体化。我觉得这可能是由于延迟执行而导致的问题。这只是我的猜测,请您尝试一下。从问题的外观来看,您的查询应该可以工作。 - Viru
似乎不起作用(目前ToList存在问题)。我会更新问题并提供一个答案(解决方法),现在有两个查询可以工作,以给出我所需的答案。 - Tjab

0

你可以在Linqpad中尝试这个。我已经将你的查询中的表和列名更改为与我的数据库匹配:

Levels
.GroupBy(c => new { c.CourseGuid, c.ModuleName })
.Where(g => g.Count() > 10)
.Select(g => g.Key.CourseGuid)

它生成的SQL查询语句如下:

-- Region Parameters
DECLARE @p0 Int = 10
-- EndRegion
SELECT [t1].[CourseGuid]
FROM (
    SELECT COUNT(*) AS [value], [t0].[CourseGuid]
    FROM [xrt].[Levels] AS [t0]
    GROUP BY [t0].[CourseGuid], [t0].[ModuleName]
    ) AS [t1]
WHERE [t1].[value] > @p0

不要使用 HAVING COUNT,而是使用 WHERE,它们在功能上是相同的。通过调整 @p0 参数,可以正确地过滤输出结果。

我建议你使用 Linqpad 来查看查询对数据的实际操作。


但这与子查询中的 HAVING 相同。 - Ivan Stoev

0

所以,我的问题的答案是:

var duplicates = session.Query<SomeClass>()
                        .GroupBy(e => new { e.Var1, e.Var2, e.Var3 })
                        .Select(s => new { s.Key.Var1, s.Key.Var2, s.Key.Var3, Count = s.Count() })
                        .ToList()
                        .Where(g => g.Count > 1)
                        .Select(g => new SomeClass() { Var1 = g.Var1, Var2 = g.Var2, Var3 = g.Var3})
                        .ToList();

感觉有点过头了,我觉得它可以更小一些,如果有人想发表意见...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接