Несколько уровней агрегации в Linq

#c# #linq

#c# #linq

Вопрос:

Я не уверен, как назвать мою проблему, хотя я упомянул в теме как «Несколько уровней агрегации».

Я хотел бы объединить различные измерения представленных данных. В этом примере я пытаюсь получить данные агрегирования с помощью SalesCode и более подробной агрегации с помощью AccountId . Таким образом, в принципе, я мог бы получить учетные записи, которые были связаны с уровнем агрегирования продаж.

Следовательно, результат, который я должен получить, должен быть таким:

введите описание изображения здесь

Мое требование — сопоставить данные со следующим классом:

 public class Earning
{
    public string EntityId
    {
        get;
        set;
    }

    public string EntityName
    {
        get;
        set;
    }

    public string EntityType
    {
        get;
        set;
    }

    public int TradeCount
    {
        get;
        set;
    }

    public int OrderCount
    {
        get;
        set;
    }

    public decimal PrincipalAmount
    {
        get;
        set;
    }

    public decimal GrossBrokerage
    {
        get;
        set;
    }

    public decimal NetBrokerage
    {
        get;
        set;
    }

    public List<Earning> Detail
    {
        get;
        set;
    }
}
  

Из следующих данных:

 List<Trade> Trades = new List<Trade>(){ 
            new Trade{
                AccountId = "ACT01", 
                SalesCode = "STEVES", 
                PrincipalAmount = 100, 
                GrossBrokerage = 0.64M,
                NetBrokerage = 0.64M
            }, 
            new Trade{
                AccountId = "ACT02", 
                SalesCode = "STEVES", 
                PrincipalAmount = 100, 
                GrossBrokerage = 0.64M,
                NetBrokerage = 0.64M
            }, 
            new Trade{
                AccountId = "ACT01", 
                SalesCode = "STEVES", 
                PrincipalAmount = 50, 
                GrossBrokerage = 0.32M,
                NetBrokerage = 0.32M
            }, 
            new Trade{
                AccountId = "ACT03", 
                SalesCode = "GRAHAMS", 
                PrincipalAmount = 100, 
                GrossBrokerage = 0.64M,
                NetBrokerage = 0.64M
            }, 
        };
  

До сих пор я пробовал следующие способы в работе, о которой я упоминаю ниже, но я не знаю, как получить агрегацию 2-го уровня, которая выполняется по идентификатору учетной записи.

Ошибка DotNetFiddle:https://dotnetfiddle.net/SxGdDD

Класс Trade выглядит следующим образом:

 public class Trade
{
    public string AccountId
    {
        get;
        set;
    }

    public string SalesCode
    {
        get;
        set;
    }

    public decimal PrincipalAmount
    {
        get;
        set;
    }

    public decimal GrossBrokerage
    {
        get;
        set;
    }

    public decimal NetBrokerage
    {
        get;
        set;
    }
}
  

Ответ №1:

Вам нужен другой GroupBy .

     var results = (
        from r in Trades
        group r by r.SalesCode
        into g
        select new Earning()
        {
            EntityId = g.Key.ToString(),
            EntityName = g.Key.ToString(),
            TradeCount = g.Count(),
            OrderCount = g.Count(),
            PrincipalAmount = g.Sum(c => c.PrincipalAmount),
            GrossBrokerage = g.Sum(c => c.GrossBrokerage),
            NetBrokerage = g.Sum(c => c.NetBrokerage),
            Detail = g.GroupBy(c=>c.AccountId).Select(c => new Earning()
       // Added GroupBy ---^^
            {
                EntityId = c.Key,
                EntityName = c.Key,
                TradeCount = c.Count(),
                OrderCount = c.Count(),
                PrincipalAmount = c.Sum(p=>p.PrincipalAmount),
                GrossBrokerage =  c.Sum(p=>p.GrossBrokerage),
                NetBrokerage = c.Sum(p=>p.NetBrokerage),

            }).ToList(),
        }).ToList();

    foreach (var item in results)
    {
        Console.WriteLine(item.EntityId);
        Console.WriteLine(string.Format("Total Principal Amount: {0}", item.PrincipalAmount.ToString()));
        Console.WriteLine(string.Format("Total Gross Brokerage Amount: {0}", item.GrossBrokerage.ToString()));
        Console.WriteLine(string.Format("Total Net Brokerage Amount: {0}", item.NetBrokerage.ToString()));

        foreach (Earning detail in item.Detail)
        {
            Console.WriteLine(string.Format("-- Detail {0}/{1}", detail.EntityId, detail.EntityName));
        }
    }
  

Комментарии:

1. Спасибо, @stephan-bauer Сработал, понравилось, прелесть! 🙂