Programming

Linq : GroupBy, 합계 및 개수

procodes 2020. 7. 26. 14:02
반응형

Linq : GroupBy, 합계 및 개수


제품 컬렉션이 있습니다

public class Product {

   public Product() { }

   public string ProductCode {get; set;}
   public decimal Price {get; set; }
   public string Name {get; set;}
}

이제 제품 코드를 기준으로 컬렉션을 그룹화하고 이름, 각 코드의 제품 또는 각 제품의 총 가격이 포함 된 개체를 반환하려고합니다.

public class ResultLine{

   public ResultLine() { }

   public string ProductName {get; set;}
   public string Price {get; set; }
   public string Quantity {get; set;}
}

그래서 GroupBy를 사용하여 ProductCode별로 그룹화 한 다음 합계를 계산하고 각 제품 코드의 레코드 수를 계산합니다.

이것이 내가 지금까지 가진 것입니다.

List<Product> Lines = LoadProducts();    
List<ResultLine> result = Lines
                .GroupBy(l => l.ProductCode)
                .SelectMany(cl => cl.Select(
                    csLine => new ResultLine
                    {
                        ProductName =csLine.Name,
                        Quantity = cl.Count().ToString(),
                        Price = cl.Sum(c => c.Price).ToString(),
                    })).ToList<ResultLine>();

어떤 이유로 합계는 올바르게 수행되지만 카운트는 항상 1입니다.

삼페 데이터 :

List<CartLine> Lines = new List<CartLine>();
            Lines.Add(new CartLine() { ProductCode = "p1", Price = 6.5M, Name = "Product1" });
            Lines.Add(new CartLine() { ProductCode = "p1", Price = 6.5M, Name = "Product1" });
            Lines.Add(new CartLine() { ProductCode = "p2", Price = 12M, Name = "Product2" });

샘플 데이터 결과 :

Product1: count 1   - Price:13 (2x6.5)
Product2: count 1   - Price:12 (1x12)

제품 1은 개수 = 2 여야합니다!

간단한 콘솔 응용 프로그램에서 이것을 시뮬레이션하려고 시도했지만 다음과 같은 결과가 나타납니다.

Product1: count 2   - Price:13 (2x6.5)
Product1: count 2   - Price:13 (2x6.5)
Product2: count 1   - Price:12 (1x12)

Product1 : 한 번만 나열해야합니다 ... 위의 코드는 pastebin에서 찾을 수 있습니다. http://pastebin.com/cNHTBSie


첫 번째 "샘플 데이터 결과"가 어디에서 오는지 이해하지 못하지만 콘솔 앱의 문제 는 각 그룹의 각 항목SelectMany 을 보는 데 사용 한다는 것 입니다.

난 당신이 원하는 것 같아요 :

List<ResultLine> result = Lines
    .GroupBy(l => l.ProductCode)
    .Select(cl => new ResultLine
            {
                ProductName = cl.First().Name,
                Quantity = cl.Count().ToString(),
                Price = cl.Sum(c => c.Price).ToString(),
            }).ToList();

사용 First()제품 이름을 얻기 위해 여기에 같은 제품 코드와 모든 제품이 동일한 제품 이름이 있다고 가정합니다. 주석에서 언급했듯이 제품 코드와 제품 이름별로 그룹화 할 수 있습니다. 이는 주어진 코드에서 이름이 항상 동일하지만 EF에서 더 나은 SQL을 생성하는 경우 동일한 결과를 제공합니다.

또한 QuantityPrice속성을 각각 intdecimal유형으로 변경해야한다고 제안합니다. 텍스트가 아닌 데이터에 대해 문자열 속성을 사용하는 이유는 무엇입니까?


The following query works. It uses each group to do the select instead of SelectMany. SelectMany works on each element from each collection. For example, in your query you have a result of 2 collections. SelectMany gets all the results, a total of 3, instead of each collection. The following code works on each IGrouping in the select portion to get your aggregate operations working correctly.

var results = from line in Lines
              group line by line.ProductCode into g
              select new ResultLine {
                ProductName = g.First().Name,
                Price = g.Sum(pc => pc.Price).ToString(),
                Quantity = g.Count().ToString(),
              };

sometimes you need to select some fields by FirstOrDefault() or singleOrDefault() you can use the below query:

List<ResultLine> result = Lines
    .GroupBy(l => l.ProductCode)
    .Select(cl => new Models.ResultLine
            {
                ProductName = cl.select(x=>x.Name).FirstOrDefault(),
                Quantity = cl.Count().ToString(),
                Price = cl.Sum(c => c.Price).ToString(),
            }).ToList();

참고URL : https://stackoverflow.com/questions/16522645/linq-groupby-sum-and-count

반응형