C#高级:利用Lambda表达式和数据库SQL进行分组、去重处理

第一部分内容可以直接在控制台程序输出

目录

一、基础分组处理

二、含列表分组处理

三、多组别分组处理(复杂,一般很少用)

四、基础去重处理

(1)程序写法

(2)SQL写法

五、一些小结

1.初始化区别

2.列表初始化注意的点

3.如何将Object转为实体


一、基础分组处理

class MainClass
{
    static List<Student> StudentList = new List<Student>()
    {
        new Student(){ Id=1,Name="小明",Classes="201班",Sex="男",Score=90},
        new Student(){ Id=2,Name="小虹",Classes="201班",Sex="女",Score=99},
        new Student(){ Id=3,Name="小二",Classes="202班",Sex="男",Score=60},
        new Student(){ Id=4,Name="小宫",Classes="202班",Sex="男",Score=50},
        new Student(){ Id=5,Name="小蓝",Classes="202班",Sex="女",Score=60},
        new Student(){ Id=6,Name="小力",Classes="202班",Sex="男",Score=70},
        new Student(){ Id=7,Name="小梅",Classes="202班",Sex="女",Score=90},
        new Student(){ Id=8,Name="小萱",Classes="203班",Sex="女",Score=20}
    };
    static void Main(string[] args)
    {
        //1.查询有多少个不一样的班级(去重)
        List<string> list1 = StudentList.Select(x => x.Classes).Distinct().ToList();
        //List<string> list2 = StudentList.Select(x => x.Classes).ToHashSet().ToList();//也可以这样写

        //【分组结构分析(以2为例)】:201班、202班、203班分别有一个列表,s是分组依据、g是组长列表,x是组员实体
        IEnumerable<IGrouping<string, Student>> temp = StudentList.GroupBy(s => s.Classes);//temp=三个列表

        // 2.每个班为一组,统计出每个班的总分
        var list2 = StudentList.GroupBy(s => s.Classes).Select(g => new { Class = g.Key, TotalScore = g.Sum(x => x.Score) }).ToList();
        Console.WriteLine(string.Join("\n", list2));

        // 3.每个班、每个性别为一组,统计出每个班、每个性别的总分
        var list3 = StudentList.GroupBy(s => new { s.Classes, s.Sex }).Select(g => new { Class = g.Key.Classes, Gender = g.Key.Sex, TotalScore = g.Sum(x => x.Score) }).ToList();
        Console.WriteLine(string.Join("\n", list3));

        //4.每个班、每个性别为一组,统计出每个班、每个性别的Score小于60的数量以及它们的姓名、代表姓名、该班该性别下学生的所有姓名
        var list4 = StudentList.GroupBy(s => new { s.Classes, s.Sex })
                                     .Select(g => new
                                     {
                                         Class = g.Key.Classes,
                                         Gender = g.Key.Sex,
                                         Count = g.Count(x => x.Score < 60),//该班该性别不及格的数量
                                         Names = string.Join(", ", g.Where(x => x.Score < 60).Select(x => x.Name)),//该班该性别不及格的姓名
                                         Names2 = g.FirstOrDefault()?.Name,//学生代表,列表第一位
                                         Names3 = g.Select(x=>x.Name)//该班该性别下学生的所有姓名(返回的是list)
                                     });
        Console.WriteLine(string.Join("\n", list4));
    }
}
class Student
{
    public int Id;
    public string Name;
    public string Classes;
    public string Sex;
    public int Score;
}

二、含列表分组处理

【数据库查表数据】ProjectID,Price,Stamonths=[time,Money]

项目名项目金额1月成本2月成本
项目1200100200
项目11005060
项目210003080
项目230010040
项目315008060

分组前——list

项目1 项目金额 [月份1金额 月份2金额](List<Stamonths>)

项目1 项目金额 [月份1金额 月份2金额]

项目2 项目金额 [月份1金额 月份2金额]

项目2 项目金额 [月份1金额 月份2金额]

项目3 项目金额 [月份1金额 月份2金额]

【前端展现页面】

项目名项目金额1月成本2月成本
项目1300150260
项目1200100200
项目11005060
项目21300130120
项目210003080
项目230010040
项目315008060
项目315008060

【说明】

1.粉色是父节点,其他为子节点

2.代码中g是加粗部分,s是非加粗部分

分组后——result_list(缩进代表是Children下的数据)

项目1 项目总金额 [月份1总金额 月份总2金额](List<Stamonths>)

        项目1 项目金额 [月份1金额 月份2金额]

        项目1 项目金额 [月份1金额 月份2金额]

项目2 项目总金额 [月份1总金额 月份总2金额]

        项目2 项目金额 [月份1金额 月份2金额]

        项目2 项目金额 [月份1金额 月份2金额]

项目3 项目总金额 [月份1总金额 月份总2金额]

        项目3 项目金额 [月份1金额 月份2金额]

代码: 

var result_list = list.GroupBy(s => new { s.ProjectID })
                        .Select(g => new
                        {
                            ProjectID = g.Key.ProjectID,//组别,即项目ID
                            TotalPrice = g.Sum(s => s.Price),//汇总数据:处理项目总金额,实现对Children的各项目金额相加
                            Stamonths = g.SelectMany(s => s.Stamonths)//汇总数据:拿出列表分组=》实现对Children的列表金额相加
                                          .GroupBy(s => s.Time)
                                          .Select(s => new
                                          {
                                              time = s.Key,
                                              Money = s.Sum(x => x.Money)
                                          })
                                          .ToList(),
                            Children=g.Select(s => new//列出子数据
                                  {
                                      s.ProjectID,
                                      s.Price,
                                      Stamonths = s.Stamonths
                                  })
                        })
                        .ToList();

三、多组别分组处理(复杂,一般很少用)

【数据库查表数据】

小组(负责人)产品名称产品经理产品批次产品成本售出批次销售价格销售日期
医疗组(xiaoxiao)专专产品新测试员2023产品批次1200默认批次100002022/1/1
医疗组(xiaoxiao)专专产品新测试员2023产品批次2100默认批次100002022/1/1
医疗组(xiaoxiao)专专产品新测试员2023产品批次1200批次230002022/1/2
医疗组(xiaoxiao)专专产品新测试员2023产品批次2100批次230002022/1/2
医疗组(xiaoxiao)专专产品新测试员2023产品批次1200批次31500NULL
医疗组(xiaoxiao)专专产品新测试员2023产品批次2100批次31500NULL

【前端展现页面】

小组(负责人)产品名称产品经理产品批次产品成本销售总收入售出批次销售价格销售日期
医疗组(xiaoxiao)专专产品新测试员2023产品批次120014500默认批次100002022/1/1
批次230002022/1/2
产品批次2100批次31500NULL

小组:产品:产品经理=1:1:1; 产品:产品批次=1:n ; 产品:售出批次=1:n ;产品批次和售出批次无直接对应关系;颜色说明了它们之间的对应关系。 

【期望返回数据格式】

[
  {
    "GroupName": "医疗组",
    "Leader": "xiaoxiao",
    "productName": "专专产品",
    "productManager": "新测试员2023",
    "productSumIncome": 300,
    "productDetails": [
        {
            "productBatchesName": "产品批次1",
            "projectCost": 200
        },
        {
            "productBatchesName": "产品批次2",
            "projectCost": 100
        }
    ],
    "salesDetails": [
        {
            "salesBatchsName": "批次3",
            "settleTime": null,
            "salesPrice": 1500
        },
        {
            "salesBatchsName": "默认批次",
            "settleTime": null,
            "salesPrice": 10000
        },
        {
            "salesBatchsName": "批次2",
            "settleTime": null,
            "salesPrice": 3000
        }
    ]
}
]

【代码编写策略】先分组,后筛选

 var resultlist = product_list.GroupBy(d => new
                 {//不同组名、不同负责人、不同产品、不同产品经理为一组
                     d.GroupName,
                     d.LeaderName,
                     d.ProductName,
                     d.ProjectManager
                 })
                 .Select(g => new
                 {//筛选出我要的内容
                     Name = g.Key.GroupName,//组别
                     Leader = g.Key.LeaderName,
                     ProductName = g.Key.ProductName,
                     ProductManager = g.Key.ProjectManager,
                     ProductSumIncome = g.GroupBy(x => x.SalesBatchsName).Sum(x=>x.FirstOrDefault()?.ProductIncome),//小组信息汇总,即【Flag】处加和,代表销售总收入
                     ProductDetails = g.GroupBy(x => x.ProBatchesName).Select(//小组信息展示(产品分组,对应蓝色框框)
                         s => new
                         {
                             ProductBatchesName = s.Key,//组别,即ProBatchesName(产品批次名)
                             ProjectCost = s.FirstOrDefault()?.ProjectCost//小组成员对应的信息
                         }),
                     SalesDetails = g.GroupBy(x => x.SalesBatchsName).Select(s => new//小组信息展示(销售分组,对应粉色框框)
                     {
                         SalesBatchsName = s.Key,//组别,即BatchesName(销售批次名)
                         SettleTime = s.FirstOrDefault()?.SettleTime,
                         SalesPrice = s.FirstOrDefault()?.ProductIncome//【Flag】
                     })
                 }) ;

四、基础去重处理

(1)程序写法

class MainClass
{
    static List<Product> ProductList = new List<Product>()
    {
        new Product(){ Id=1,Name="产品1号",CustormuerName="李老板",Batches="批次1"},
        new Product(){ Id=1,Name="产品1号",CustormuerName="王老板",Batches="批次1"},
        new Product(){ Id=1,Name="产品1号",CustormuerName="王老板",Batches="批次1"},
        new Product(){ Id=1,Name="产品1号",CustormuerName="李老板",Batches="批次2"},
        new Product(){ Id=2,Name="产品2号",CustormuerName="苏老板",Batches="批次1"},
        new Product(){ Id=2,Name="产品2号",CustormuerName="李老板",Batches="批次1"}
    };
    static void Main(string[] args)
    {

        //(1)数据一样的去重
        var list1_1 =  ProductList
                        .GroupBy(p => new { p.Id, p.Name, p.CustormuerName, p.Batches })
                        .Select(g => g.First())
                        .ToList();

        //(2)产品名字一样的去重,返回第一条
        var list1_2 = ProductList.DistinctBy(x => x.Name).ToList();

        //(3)产品名字和客户名字一样的去重,返回第一条
        var list1_3 = ProductList.DistinctBy(x => new 
            { 
                x.Name, x.CustormuerName 
            }).ToList();
    }
}
class Product
{
    public int Id;
    public string Name;
    public string CustormuerName;
    public string Batches;
}

(2)SQL写法

--(1)内容一样去重,返回第一条
SELECT Name, CustormuerName, Batches, Income
FROM ProductTable
GROUP BY Name, CustormuerName, Batches, Income

--(2)产品名字一样的去重,返回第一条
SELECT Name
FROM ProductTable
GROUP BY Name

--(3)产品名字和客户名字一样的去重,返回第一条
SELECT Name, CustormuerName
FROM ProductTable
GROUP BY Name, CustormuerName

【SQL分组注意】
1.GROUP BY 字段要和SELECT字段一致
2.聚合函数使用:MAX可以取分组后的第一个代表元素,COUNT(*)可以表示分组之后该小组有多少条数据,AVG,SUM等函数是计算小组某个字段的平均值和总和的。
3.如果想取小组中的指定序号的成员,需要用ROW_NUMBER()关键字处理。 

五、一些小结

1.初始化区别

  • new List<object>(resultlist):将 resultlist 中的元素逐个复制到新的列表中。
  • new List<object>{resultlist}:将 resultlist 作为单个元素添加到新的列表中。
  • 第一种结构就是List<object>,即 ["item1", "item2", "item3"]
  • 第二种结构是List<object>下带有resullist,即 [{"resultlist": ["item1", "item2", "item3"]}]

2.列表初始化注意的点

  • 需要写两个new
//【字段】
public class ProjectIncomeResult
{
     public decimal TotalPriceSum { get; set; }
     public List<MonthlyIncomSums> MonthlyIncomeSumList { get; set; }
}
//【写法】
var resultlist = new List<ProjectIncomeResult> { 
          new ProjectIncomeResult
          {
               TotalPriceSum=10000,
               MonthlyIncomeSumList = monthlyIncomeSums 
          }
};
  • 封装的写法(result是已写好的结构)

var resultlist = new List<ProductResult> (result)

3.如何将Object转为实体

【步骤】:

     第一步,照着object类写实体字段。(也可以叫AI写)

     第二步,在object类的【Select】里面的【new】后面加上具体的实体类

     第三步,在object类的屁股后加【.ToList()】

【原来的object类】

var resultlist = product_list.GroupBy(d => new
               {
                    d.AmoebaName,
                    d.AmoebaLeaderName,
               })
               .Select(g => new 
               {
                    AmoebaName = g.Key.AmoebaName,
                    AmoebaLeader = g.Key.AmoebaLeaderName,
                    ProductSumCost = g.GroupBy(x=>x.ProBatchesName).Sum(x=>x.FirstOrDefault()?.ProjectCost),
                    ProductSumIncome = g.GroupBy(x => x.BatchsName).Sum(x=>x.FirstOrDefault()?.ProductIncome),
                    SalesDetails = g.GroupBy(x => x.BatchsName).Select(s => new 
                    {
                         SalesBatchsName = s.Key,
                         SettleTime = s.FirstOrDefault()?.SettleTime,
                         SalesPrice = s.FirstOrDefault()?.ProductIncome
                    })
               });

【第一步,写字段】

public class ProductResult
{
     public string AmoebaName { get; set; }
     public string AmoebaLeader { get; set; }
     public double? ProductSumCost { get; set; }
     public double? ProductSumIncome { get; set; }
     public IEnumerable<SalesDetail> SalesDetails { get; set; }//实体下面有集合
}
public class SalesDetail
{
     public string SalesBatchsName { get; set; }
     public DateTime? SettleTime { get; set; }
     public double? SalesPrice { get; set; }
}

【第二三步,加具体实体和加Tolist()】

var resultlist = product_list.GroupBy(d => new
               {
                    d.AmoebaName,
                    d.AmoebaLeaderName,
               })
               .Select(g => new ProductResult
               {
                    AmoebaName = g.Key.AmoebaName,
                    AmoebaLeader = g.Key.AmoebaLeaderName,
                    ProductSumCost = g.GroupBy(x=>x.ProBatchesName).Sum(x=>x.FirstOrDefault()?.ProjectCost),
                    ProductSumIncome = g.GroupBy(x => x.BatchsName).Sum(x=>x.FirstOrDefault()?.ProductIncome),
                    SalesDetails = g.GroupBy(x => x.BatchsName).Select(s => new SalesDetail
                    {
                         SalesBatchsName = s.Key,
                         SettleTime = s.FirstOrDefault()?.SettleTime,
                         SalesPrice = s.FirstOrDefault()?.ProductIncome
                    })
               }).ToList() ;

【注意】实体类需用等于号赋值,不能省略

result.ReturnData = new ManPowAllResult 
                    {
                        resultlist=resultlist,
                        allSumlist=allSumlist
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值