sensei
sensei

Reputation: 7542

Linq return data if there are no values with corresponding entity

Example query:

    var results = await campaignList
        .GroupBy(x => x.Campaign)
        .Select(c => new ReportModel
        {
            CampaignId = c.Key.Id,
            CoregName = c.Key.Name,
            TotalVisitors = startDate == null || endDate == null ? c.Key.LogPixelCalls.Count : c.Key.LogPixelCalls.Count(x => x.CreatedOn >= startDate && x.CreatedOn <= endDate),
            TotalUsers = c.Count(),
            TotalPaidUsers = c.Count(x => x.UserSignature.StripeCustomerId != null),
            TotalUserConversion = !c.Any() || c.Key.LogPixelCalls.Count == 0 ? 0 : (decimal)c.Count() / (decimal)c.Key.LogPixelCalls.Count * 100,
            TotalPaidUserConversion = c.Count(x => x.UserSignature.StripeCustomerId != null) == 0 || !c.Any() ? 0 : (decimal)c.Count(x => x.UserSignature.StripeCustomerId != null) / (decimal)c.Count() * 100
        })
        .OrderByDescending(c => c.TotalPaidUsers)
        .ToListAsync();

It selects Campaigns which have data connected with corresponding CampaignId. How to select all Campaigns and if there is no data in other tables, fill 0 values in .Select ?

Example: Campaign 1, 44, 22, 33 Campaign 2, 0, 0, 0

Campaign 2 doesn't have any data, but I still want to show it in result.

Edit: Tried to use GroupJoin without success:

var resultinho = campaigns.GroupJoin(
                results,
                foo => foo.Id,
                bar => bar.CampaignId,
                (x, y) => new { Foo = x, Bar = y })
                .SelectMany(
                    x => x.Bar.DefaultIfEmpty(),
                    (x, y) => new ReportModel
                    {
                        CampaignId = x.Bar.FirstOrDefault().CampaignId,
                        CoregName = x.Bar.FirstOrDefault().CoregName,
                        TotalVisitors = x.Bar.FirstOrDefault().TotalVisitors,
                        TotalUsers = x.Bar.FirstOrDefault().TotalUsers,
                        TotalPaidUsers = x.Bar.FirstOrDefault().TotalPaidUsers,
                        TotalUserConversion = x.Bar.FirstOrDefault().TotalUserConversion,
                        TotalPaidUserConversion = x.Bar.FirstOrDefault().TotalPaidUserConversion
                    })
                .ToList();

Upvotes: 0

Views: 58

Answers (2)

Dexion
Dexion

Reputation: 1101

group/sum campaign data first and left join the campaign with the grouped results

var cd = campaigns.GroupBy (c => new {c.ID} ).Select (cp =>
     new {
        cId= cp.Key.ID,
        TotalUsers = cp.Count(),
        TotalSum= cp.Sum( x=>x.UsersByCampaign)
        ...
        } );

var results = campaignList.ForEach( cl => cd.Where( cdd => cdd.cId == cl.Id)
.Select(cdd => new { CampaignId  = cdd.CId, TotalVisitors  = cdd.TotalUsers , .. })
.DefaultIfEmpty( new { CampaignId  = cdd.CId, TotalVisitors  =0 , .. });

Upvotes: 1

sensei
sensei

Reputation: 7542

I did like this:

var resultsWithEmtpyCampaigns = campaigns.GroupJoin(
                results,
                camp => camp.Id,
                campResult => campResult.CampaignId,
                (x, y) => y.Select(c => new ReportModel
                {
                    CampaignId = y.FirstOrDefault().CampaignId,
                    CoregName = y.FirstOrDefault().CoregName,
                    TotalVisitors = y.FirstOrDefault().TotalVisitors,
                    TotalUsers = y.FirstOrDefault().TotalUsers,
                    TotalPaidUsers = y.FirstOrDefault().TotalPaidUsers,
                    TotalUserConversion = y.FirstOrDefault().TotalUserConversion,
                    TotalPaidUserConversion = y.FirstOrDefault().TotalPaidUserConversion,
                    ReportCountryList = y.FirstOrDefault().ReportCountryList
                })
                     .DefaultIfEmpty(new ReportModel
                     {
                         CampaignId = x.Id,
                         CoregName = x.Name,
                         TotalVisitors = 0,
                         TotalUsers = 0,
                         TotalPaidUsers = 0,
                         TotalUserConversion = 0,
                         TotalPaidUserConversion = 0
                     }))
                .SelectMany(g => g).ToList();

            return
                resultsWithEmtpyCampaigns;

Upvotes: 1

Related Questions