LinQ查询将同一张表分组两次

时间:2020-02-12 11:06:26

标签: c# entity-framework linq

我需要一些帮助。
问题:我有User和一个MedalTransaction班。 用户可以分配奖章,也可以接收奖章。 MedalTransaction有两个属性,分别是用户ID,分别为OriginDestination


我尝试过的事情:

var q = (from user in companyUsers
         join mt in Context.MedalTransactions
         on user.Id equals mt.Destination into medalTransactions

         from mt in medalTransactions.DefaultIfEmpty()

         group new { user, mt } by new { mt.Destination } into receivedMedals

         select new User
         {
             Id = receivedMedals.Select(u => u.user.Id).FirstOrDefault(),
             Name = receivedMedals.Select(u => u.user.Name).FirstOrDefault(),
             Company = receivedMedals.Select(u => u.user.Company).FirstOrDefault(),

             TotalAcquiredMedals = receivedMedals
                .Where(m => m.mt.Destination == m.user.Id && m.mt.Origin != systemId)
                .Sum(m => m.mt.Quantity)                       

         })
        .OrderByDescending(u => u.TotalAcquiredMedals);

这有效,但仅适用于获得的奖章。 我想在用户实例创建时设置其他属性TotalAssignedMedals。 我尝试了多个group by,但从未获得想要的结果,我什至不知道是否可以这样做。

感谢您的帮助


编辑 问题已解决,最终代码:

var q = (from user in companyUsers

                 join mt in Context.MedalTransactions
                 on user.Id equals mt.Destination into receivedMedals

                 join mt2 in Context.MedalTransactions
                 on user.Id equals mt2.Origin into assignedMedals

                 from mtReceived in receivedMedals.DefaultIfEmpty()
                 from mtAssigned in assignedMedals.DefaultIfEmpty()

                 group new { user, mtReceived, mtAssigned } by new { user.Id } into medalTransactions

                 select new User
                 {
                     Id = medalTransactions.Select(_ => _.user.Id).FirstOrDefault(),
                     Name = medalTransactions.Select(_ => _.user.Name).FirstOrDefault(),
                     Company = medalTransactions.Select(_ => _.user.Company).FirstOrDefault(),

                     TotalAcquiredMedals = medalTransactions
                        .DistinctBy(m => m.mtReceived.Id)
                        .Where(m => m.mtReceived.Origin != systemId)
                        .Sum(m => m.mtReceived.Quantity),

                     TotalAssignedMedals = medalTransactions
                        .DistinctBy(m => m.mtAssigned.Id)
                        .Where(m => m.mtAssigned.Destination != systemId)
                        .Sum(m => m.mtAssigned.Quantity)

                 })
                .OrderByDescending(u => u.TotalAcquiredMedals);

1 个答案:

答案 0 :(得分:1)

也许是这样的

from user in companyUsers

join mt in Context.MedalTransactions
on user.Id equals mt.Destination into destinations

join mt2 in Context.MedalTransactions
on user.Id equals mt2.Origin into origins

from mtd in mt.DefaultIfEmpty()
from mto in mt2.DefaultIfEmpty()

group new { user, mtd, mto } by new { user.Id } into medals
select new {user.Id, user.Name, ..., 
    TotalAcquiredMedals = mtd.Where(_ => _ != null).Distinct().Count(), 
    TotalAssignedMedals = mto.Where(_ => _ != null).Distinct().Count()
}