group by ... into g 把分组后的整个结果集存入变量 g,后续可以:
- 通过
g.Key访问分组键 - 通过
g.Count()、g.Sum()等聚合方法统计每组数据 - 通过
where对分组结果进行过滤(等效 SQL 的HAVING)
内存集合示例
string[] words = { "apples", "blueberries", "oranges", "bananas", "apricots" };
var q = from w in words
group w by w[0] into fruitGroup // 按首字母分组
where fruitGroup.Count() >= 2 // 只保留数量 >= 2 的组
select new
{
FirstLetter = fruitGroup.Key,
Words = fruitGroup.Count()
};
var list = q.ToList();Code language: JavaScript (javascript)
结果:
| FirstLetter | Words |
|---|---|
| a | 2(apples、apricots) |
| b | 2(blueberries、bananas) |
数据库查询示例
using (var db = new DataClasses1DataContext())
{
var q = from m in db.Money
group m by m.name into g // 按名字分组,每组存入 g
select new
{
name = g.Key, // 分组键(name 值)
count = g.Count() // 每组记录数
};
var list = q.ToList();
}Code language: JavaScript (javascript)
生成的 SQL:
SELECT COUNT(*) AS [count], [t0].[name]
FROM [dbo].[Money] AS [t0]
GROUP BY [t0].[name]Code language: CSS (css)
into 后的常用操作
| 操作 | 写法 | 等效 SQL |
|---|---|---|
| 计数 | g.Count() | COUNT(*) |
| 求和 | g.Sum(m => m.je) | SUM(je) |
| 平均值 | g.Average(m => m.je) | AVG(je) |
| 最大值 | g.Max(m => m.je) | MAX(je) |
| 最小值 | g.Min(m => m.je) | MIN(je) |
| 过滤分组 | where g.Count() >= 2 | HAVING COUNT(*) >= 2 |
into + where 等效 HAVING
var q = from m in db.Money
group m by m.name into g
where g.Sum(m => m.je) > 1000 // 只保留总金额 > 1000 的组
select new
{
name = g.Key,
total = g.Sum(m => m.je)
};Code language: JavaScript (javascript)
where写在group by ... into g之后,翻译为 SQL 的HAVING子句,在数据库端过滤分组结果。
Previous: 动态拼接查询(IQueryable 延迟执行)
Next: let 语句的完整用法