Win10环境借助DockerDesktop部署大数据时序数据库Apache Druid的操作做法实用指南
2026-09-15
2026-09-21 0
C# 中用 LINQ 处理数据,可按“数据源 → Where 筛选 → OrderBy/ThenBy 排序 → GroupBy 分组聚合 → Join 关联”的思路组合操作。这些操作步骤不必每次全部采用;先明确最终应当什么形状的结果,再选操作符,能避免为了“用 LINQ”而制造不必要的中间集合。

Microsoft C# 文档将查询定义为描述从数据源取回何种数据的指令集;查询变量和实际执行时点并不总是同一件事。
record Department(int Id, string Name);
record Employee(int Id, string Name, int DepartmentId, decimal Salary, bool Active);
var departments = new[]
{
new Department(1, "Engineering"),
new Department(2, "Support"),
new Department(3, "Sales")
};
var employees = new[]
{
new Employee(1, "Ada", 1, 18000m, true),
new Employee(2, "Bo", 1, 15000m, true),
new Employee(3, "Chen", 2, 12000m, false),
new Employee(4, "Ding", 2, 13500m, true),
new Employee(5, "Evan", 3, 16000m, true)
};
下面所有示例都使用这两个数组,这样可以看清每一步如何改变结果。
找出仍在职且月薪不低于 15000 的员工:
var selected = employees.Where(employee =>
employee.Active && employee.Salary >= 15000m);
Where 接收一个返回布尔值的条件函数。对于 LINQ to Objects,结果在枚举时逐项判断;此时 selected 还不是已经复制好的新列表。
从实际处理来看,先按部门升序,部门内再按薪资降序,同薪资按姓名升序:
var ordered = employees
.Where(employee => employee.Active)
.OrderBy(employee => employee.DepartmentId)
.ThenByDescending(employee => employee.Salary)
.ThenBy(employee => employee.Name);
第一个排序键用 OrderBy 或 OrderByDescending,后续键必须用 ThenBy 系列。如果连续调用两次 OrderBy,第二次会建立新的主排序,不是在第一个键内再排。
按部门统计在职人数、平均薪资和最高薪资:
var summaries = employees
.Where(employee => employee.Active)
.GroupBy(employee => employee.DepartmentId)
.Select(group => new
{
DepartmentId = group.Key,
Count = group.Count(),
AverageSalary = group.Average(employee => employee.Salary),
MaxSalary = group.Max(employee => employee.Salary)
})
.OrderBy(summary => summary.DepartmentId)
.ToList();
GroupBy 返回一组 IGrouping,group.Key 是分组键,group 本身可枚举该组内元素。用 Select 立即投影为统计结果,能让后续代码不必携带整组原始员工。
将员工的 DepartmentId 与部门的 Id 相等项联接,输出部门名:
var directory = employees
.Where(employee => employee.Active)
.Join(
departments,
employee => employee.DepartmentId,
department => department.Id,
(employee, department) => new
{
employee.Name,
Department = department.Name,
employee.Salary
})
.OrderBy(row => row.Department)
.ThenByDescending(row => row.Salary)
.ToList();
从实际处理来看,Join 的四个关键参数依次是:右侧数据源、左侧键、右侧键、结果投影。它是内联接,没有匹配部门的员工不会出现。
如果需要“所有部门,即使没有员工也要显示”,先用 GroupJoin 得到每个部门的员工组:
var departmentCounts = departments.GroupJoin(
employees.Where(employee => employee.Active),
department => department.Id,
employee => employee.DepartmentId,
(department, members) => new
{
Department = department.Name,
ActiveCount = members.Count()
});
Sales 等有员工的部门会显示真实数量,没有匹配项的部门会得到 0。
要生成“各部门高薪在职员工数和平均薪资”,可先筛选,再按部门分组,然后与部门表联接,最后排序:
var salaryGroups = employees
.Where(employee => employee.Active && employee.Salary >= 13000m)
.GroupBy(employee => employee.DepartmentId)
.Select(group => new
{
DepartmentId = group.Key,
Count = group.Count(),
Average = group.Average(employee => employee.Salary)
});
var report = salaryGroups
.Join(
departments,
group => group.DepartmentId,
department => department.Id,
(group, department) => new
{
Department = department.Name,
group.Count,
group.Average
})
.OrderByDescending(row => row.Average)
.ThenBy(row => row.Department)
.ToList();
ToList() 是这份报表的执行边界。它之前是查询定义,之后是当时结果的快照。
从实际处理来看,很多返回 IEnumerable 或 IQueryable 的 LINQ 操作只构建查询,到 foreach、ToList、Count 等枚举/终结操作时才执行。因此:
ToList();IQueryable,自定义 C# 方法未必能翻译为 SQL,应查看 provider 的支持和实际生成查询。OrderBy 而非 ThenBy。Count,需要时先选取唯一标识。LINQ 的关键不是背下所有操作符,而是按结果形状组织步骤:Where 决定保留哪些项,OrderBy/ThenBy 决定顺序,GroupBy 将相同键变成组,Join 用共同键合并两个数据源。最后明确执行边界,并根据 LINQ to Objects 还是数据库 provider 验证实际行为。