将数据分组并为图表返回序列的LINQ

本文关键字:返回 LINQ 数据 | 更新日期: 2023-09-27 18:13:09

假设我们有一个简化的Orders实体,具有以下属性:Id (int, PK), orderDate (datetime,非null)和productCategory (string,非null)。

LINQ to Entities查询返回每个类别的订单计数,按月分组,过去12个月,按年,按月订购,该是什么?

输出应该是这样的,为了将其作为Highcharts折线图的级数传递,使用JQuery.getJSON():

[{
   name: 'Dairy',
   data: [23, 27, 32, 44, 21, 30, 11, 0, 9, 24, 3, 19]
 },
 {
   name: 'Frozen',
   data: [11, 4, 0, 6, 8, 10, 17, 24, 18, 8, 23, 10]
}]

即每个类别有12个值,包括0。

将数据分组并为图表返回序列的LINQ

这似乎可以工作:

var orders = from o in orderList.ToList().Where(x => x.orderDate >= DateTime.Now.AddYears(-1)).GroupBy(x => x.productCategory)
        select new {
            name = o.Key,
            data = ((Func<int[]>)(() => {
                var months = new int[12];        
                for (int i = 0; i < 12; i++) {
                    months[i] = o.Where(x => x.productCategory == o.Key && x.orderDate.Month == i).Count();
                }
                return months;
            }))()
        };

首先,我们筛选日期在去年的订单。然后按productCategory字段对结果进行分组。从这个分组中,我们创建一个匿名投影类。这里,我们将name字段设置为分组键(类别)。为了填充data字段,我们使用一个匿名函数枚举每个月,并计算与我们分组的月号和产品类别匹配的每条记录。

这允许我们输入没有数据的月份的0计数

 var months = Enumerable.Range(1, 12);
 var max = DateTime.Now.AddYears(-1);
 var result = data.Where(d => d.OrderDate >= max)
                .GroupBy(d => d.ProductCategory)
                .Select(g =>
                        new
                        {
                            Name = g.Key,
                            Data =( 
                            from m in months
                            join  d in
                                g.OrderBy(gg => gg.OrderDate.Year)
                                .ThenBy(gg => gg.OrderDate.Month)
                                .GroupBy(gg => gg.OrderDate.Month)
                                on m equals d.Key into gj
                                from j in gj.DefaultIfEmpty()
                                    select j.Key != null ? j.Count() : 0)
                        }).ToArray();