1. 为什么需要排序与分组?
在数据处理中,排序(ORDER BY)和分组(GROUP BY)是最常用的两种数据整理方式。电商网站的商品价格筛选、学生成绩的班级排名、销售数据的区域统计等场景都需要这两种操作。在C#中通过MySqlConnector(官方推荐的MySQL .NET驱动)执行这类查询,既能保证执行效率,又能实现原生SQL的完整功能。
2. 环境准备与基础连接
2.1 安装MySqlConnector
通过NuGet包管理器安装最新稳定版:
Install-Package MySqlConnector -Version 2.3.0
2.2 建立数据库连接
using MySqlConnector;
// 创建连接字符串(根据实际情况修改参数)
var connectionString = "Server=localhost;User ID=root;Password=123456;Database=SchoolDB";
// 创建连接对象
using var connection = new MySqlConnection(connectionString);
try
{
await connection.OpenAsync();
Console.WriteLine("数据库连接成功!");
}
catch (Exception ex)
{
Console.WriteLine($"连接失败:{ex.Message}");
}
3. 数据排序实战
3.1 单字段基础排序
查询学生表并按年龄升序排列:
var sql = @"
SELECT StudentName, Age, ClassName
FROM Students
ORDER BY Age ASC; -- ASC表示升序,DESC表示降序";
using var command = new MySqlCommand(sql, connection);
using var reader = await command.ExecuteReaderAsync();
Console.WriteLine("姓名\t年龄\t班级");
while (await reader.ReadAsync())
{
Console.WriteLine($"{reader["StudentName"]}\t{reader["Age"]}\t{reader["ClassName"]}");
}
3.2 多字段组合排序
当年龄相同时按姓名首字母排序:
var sql = @"
SELECT StudentName, Score
FROM ExamResults
ORDER BY Score DESC, StudentName ASC; -- 先按分数降序,再按姓名升序";
4. 数据分组深度应用
4.1 基础分组统计
统计每个班级的平均分:
var sql = @"
SELECT ClassName, AVG(Score) AS AvgScore
FROM ExamResults
GROUP BY ClassName;";
// 执行查询后处理结果
while (await reader.ReadAsync())
{
Console.WriteLine($"班级:{reader["ClassName"]},均分:{reader.GetDecimal("AvgScore"):F2}");
}
4.2 分组后筛选(HAVING)
筛选平均分高于80的班级:
var sql = @"
SELECT ClassName, AVG(Score) AS AvgScore
FROM ExamResults
GROUP BY ClassName
HAVING AvgScore > 80;"; -- HAVING用于分组后筛选
5. 关联技术:参数化查询
防止SQL注入的安全写法:
var minScore = 90;
var sql = @"
SELECT StudentName
FROM ExamResults
WHERE Score > @scoreThreshold
ORDER BY Score DESC";
var command = new MySqlCommand(sql, connection);
command.Parameters.AddWithValue("@scoreThreshold", minScore); // 参数化传值
6. 典型应用场景分析
6.1 动态排序场景
Web应用中根据用户选择的排序字段动态生成SQL:
string sortField = Request.Query["sortBy"]; // 从前端获取排序字段
var validColumns = new HashSet<string> { "Score", "Age", "BirthDate" };
if (validColumns.Contains(sortField)) {
sql += $" ORDER BY {sortField} DESC";
}
6.2 多层分组报表
生成销售数据的区域-产品类型二级分组报表:
var sql = @"
SELECT Region, ProductType, SUM(SalesAmount)
FROM SalesRecords
GROUP BY Region, ProductType
ORDER BY Region ASC, SUM(SalesAmount) DESC";
7. 技术方案优缺点
优势特性:
- 原生SQL支持:可直接使用MySQL特有语法(如WITH ROLLUP)
- 高性能:基准测试显示比Entity Framework快3倍以上
- 轻量化:安装包仅200KB,适合容器化部署
需要改进:
- 缺乏LINQ支持:需手动编写SQL语句
- 异步超时设置:默认15秒需根据场景调整
var command = new MySqlCommand(sql, connection)
{
CommandTimeout = 30 // 设置超时时间为30秒
};
8. 关键注意事项
- 连接池管理:默认开启连接池,建议保持开启状态
- 数据类型映射:MySQL的UNSIGNED INT需映射为C#的ulong类型
- 索引优化:对GROUP BY字段建议创建组合索引
CREATE INDEX idx_group ON SalesRecords (Region, ProductType);
9. 开发调试技巧
启用详细日志记录:
var connectionString = "Server=...;Logging=True;";
在开发环境查看实际执行的SQL:
// 输出带参数的完整SQL
Console.WriteLine(command.CommandText);
foreach (MySqlParameter p in command.Parameters)
{
Console.WriteLine($"{p.ParameterName} = {p.Value}");
}
10. 总结与选择建议
对于需要直接控制SQL、追求极致性能的C#项目,MySqlConnector是连接MySQL的最佳选择。在涉及复杂分组(如分组后排序TOP N记录)的场景中,建议在数据库层完成计算,相比在C#中处理内存数据,效率可提升10倍以上。