基于LINQ中的分组和动态范围计数

时间:2014-10-31 11:58:01

标签: c# performance linq linq-to-entities

我需要根据范围获取分组数据和计数。 这不是实际情况,但它是我需要做的类似的简单案例:

public class ProductSale{
 public long ID {get; set;}
 public long ProductID {get; set;}
 public DateTime SaleDate {get; set;}
 ...
}

public class Product{
  public long ID {get; set;}
  public long ProductCategoryID {get; set;}
  public string Description {get; set;}
  ...
}

public class ProductCategory{
  public long ID {get; set;}
  public string Description {get; set;}
  ...
}

public class ProductSaleRange{
 public long ID {get; set;}
 public long Range{get; set;}
}

此ProductSaleRange表包含数据 1:4,2:9,3:15

计算销售范围0-4,5-9,10-15和15 +

根据上述结构,我们需要生成日期范围之间的销售报告      ProductCategoryName |在给定日期范围内产品的总数量|产品销售0-4倍| productsold 5-9次|产品销售10-15次|产品销售15次以上

这些范围是动态的,来自Productsale范围表。 我需要使用C#/ Linq生成reort以获得上述格式的结果 结果是按产品类别分组,在该类别中销售的产品总数和在该范围内销售的产品数量。 假设有一个类别的18个产品,这15个产品共有76个销售,3个产品销售6次,2个销售11次,没有人销售15次以上 所以我的报告看起来像

enter image description here

我通过按ProductCategoryID对ProductSale进行分组来获得总计数,并且我为每个类别的每个范围循环productSale。 我想删除循环,因为这不会给出快速的结果,我需要以更好的方式实现使用Linq获得这些结果。

提前感谢任何指导。

已更新

这是我的代码,直到现在

public static IEnumerable<ProductSaleRanges> GetGetProductSale(DateTime startDate, DateTime endDate)
    {
        using (var db = new Entities())
        {
            var sales= db.ProductSale.Where(x =>  x.SaleDate  >= startDate && x.SaleDate  <= endDate).ToList();
            var result = (from r in sales= 
                          group r by r.Product.ProductCategoryID  
                         into g
                         select new ProductSaleRanges
                                    {
                                        ID = g.Key.ToString(),
                                        ProductCategory= ..,//fetch name
                                        ProductSaleRanges=GetSaleRangesByCategory(sales , g.Key)
                                    }).ToList();
            return result;
        }

    }
public static List<ProductSaleRangesByCategory> GetSaleRangesByCategory(IEnumerable<ProductSale> sales, Int64 categoryid)
    {
        var productList = (from s in sales
                                where s.Product.ProductCategoryID  == categoryid
                                group s by s.ProductID
                                    into sg
                                    select new ProductList { ProductID = sg.Key, SaleCount = sg.Count() }).ToList();
        var result = GetSaleRangeDetails(productList );
        return result;
    }

 public static List<SaleThreshold> GetSaleRangeDetails(IEnumerable<ProductList > productList) 
    {
        int minCnt = 0;
        int maxCnt = 0;
        int cnt = 0;
        var model = ProductSaleRange.GetProductSaleRange().ToList();//returns all sale ranges from DB
        var listLength = model.Count;
        var index = 0;

        var result = model.Select(x =>
        {
            string text;
            if (index == listLength - 1)
            {
                minCnt = (x.Range);
                maxCnt = 365;       //days in year

                cnt = GetSaleCount(productList, minCnt, maxCnt);
                text = x.Range.ToString() + "+ Times";
            }
            else
            {
                minCnt = (x.Range + 1);
                maxCnt = model[index + 1].Range;
                cnt = GetSaleCount(productList, minCnt, maxCnt);
                text =
                    (x.Range + 1).ToString() + "-" + (model[index + 1].Range).ToString() + " Times";
            }
            index++;
            return new SaleThreshold
            {
                ID = x.ID,
                Intervals = text,
                Sale= cnt,
            };
        }).ToList();

        return result;
    }

public static int GetSaleCount(IEnumerable<ProductList> productList, int minCnt, int maxCnt)
    {
        int cnt = productList.Where(x => x.SaleCount  >= minCnt && x.SaleCount  <= maxCnt)
            .Select(x => x.ProductID).Count();

        return cnt;
    }

0 个答案:

没有答案