var product = db.Products
.Where(x => x.ProductKey == 310)
.Join(db.InternetSales, p => p.ProductKey,
c => c.ProductKey, (p, c) => c)
.SingleOrDefault();
This is my query but I dont know how to group it by ProductName and Sum the Sales Amount.
Try this:
var product = db.Products.Where(x => x.ProductKey == 310)
.Join(db.InternetSales, p => p.ProductKey,
c => c.ProductKey, (p, c) => c)
.GroupBy(c => c.ProductName)
.Select(g => new { g.Key, TotalSales = g.Sum(x => x.Sales) })
.SingleOrDefault();
Or if you only need the sum, try this:
var totalSales = db.Products.Where(x => x.ProductKey == 310)
.Join(db.InternetSales, p => p.ProductKey,
c => c.ProductKey, (p, c) => c)
.GroupBy(c => c.ProductName)
.SingleOrDefault()
.Sum(x => x.Sales);
You don't need Join at all, because you already have ProductKey which is then used to join InternetSales table.
I think you can end up with following:
var TotalSales = db.InternetSales
.Where(s => s.ProductKey == 310)
.Select(s => s.Sales)
.Sum();
Related
I am developing something to show a pie chart of the users' age with slicing them as
0-17
18-34
35-44
44-54
55+
Not Available
here i am getting the ages based on the date range;
var aggaResonse = client.Search<JSModel>(a => a
.Size(0)
.Query(q => q.Bool(b => b.Must(m => m
.DateRange(date => date
.Field(p => p.CreatedDate)
.GreaterThanOrEquals(start)
.LessThanOrEquals(end)),
m =>
m.Term(t => t.Field(f => f.StepType.Suffix("keyword")).Value("User"))
)
))
.Aggregations(c => c.DateRange(nameof(AgeModel), x => x
.Field(f => f.BirthDate)
.Ranges(r => r.From(DateMath.Now.Subtract("17y")).To(DateMath.Now).Key(nameof(result.Years_0_17)),
r => r.From(DateMath.Now.Subtract("34y")).To(DateMath.Now.Subtract("18y")).Key(nameof(result.Years_18_34)),
r => r.From(DateMath.Now.Subtract("44y")).To(DateMath.Now.Subtract("35y")).Key(nameof(result.Years_35_44)),
r => r.From(DateMath.Now.Subtract("54y")).To(DateMath.Now.Subtract("45y")).Key(nameof(result.Years_45_54)),
r => r.From(DateMath.Now.Subtract("120y")).To(DateMath.Now.Subtract("55y")).Key(nameof(result.Years_55_Plus))
)
)
));
if (!aggaResonse.IsValid)
return result;
result.Years_0_17 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_0_17)).DocCount;
result.Years_18_34 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_18_34)).DocCount;
result.Years_35_44 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_35_44)).DocCount;
result.Years_45_54 = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_45_54)).DocCount;
result.Years_55_Plus = aggaResonse.Aggregations.Range(nameof(AgeModel)).Buckets.Single(c => c.Key == nameof(result.Years_55_Plus)).DocCount;
return result;
what i need is to have a "Not Available" slice for users who has NULL as birthdate with mapping it as;
result.Not_Available = ....;
Any suggestions with following best practices for nested NEST aggs ?
I was thinking to run another search which i guess it's not the best practice.
After digging documentations too much, here is the solution i wrote;
I added a "Missing" attribute to the current aggregation;
&& c.Missing("DOBMissing", x => x.Field(f => f.BirthDate))
So it became like;
.Aggregations(c => c.DateRange(nameof(AgeModel), x => x
.Field(f => f.BirthDate)
.Ranges(r => r.From(DateMath.Now.Subtract("17y")).To(DateMath.Now).Key(nameof(result.Years_0_17)),
r => r.From(DateMath.Now.Subtract("34y")).To(DateMath.Now.Subtract("18y")).Key(nameof(result.Years_18_34)),
r => r.From(DateMath.Now.Subtract("44y")).To(DateMath.Now.Subtract("35y")).Key(nameof(result.Years_35_44)),
r => r.From(DateMath.Now.Subtract("54y")).To(DateMath.Now.Subtract("45y")).Key(nameof(result.Years_45_54)),
r => r.From(DateMath.Now.Subtract("120y")).To(DateMath.Now.Subtract("55y")).Key(nameof(result.Years_55_Plus))
)
) &&
c.Missing("DOBMissing", x => x.Field(f => f.BirthDate))
)
And i'd accessed the "missing" part of aggregation as following;
result.Not_Available = aggaResponse.Aggregations.Missing("DOBMissing").DocCount;
I have a scenario where in case there is a specific boolean value satisfied (office_debit_total line) I can get amount directly from a column otherwise I need to calculate it by grouping some specific values, here's the code:
var result = products.Select(p => new ResponseDto()
{
customer_id = p.CustomerId,
office_debit_date = p.OfficeDebitDate.Value.ToString(),
office_debit_id = p.OfficeDebitId.ToString(),
office_debit_total = p.OfficeEnum == SomeEnum.ValueType ? p.OfficeAmount.ToString() : totalAmounts[p.OfficeDebitId].ToString(),
payment_method = p.PaymentMethod.Value.ToString(),
}).ToList();
As it's possible to be seen office_debit_total is calculated depending on enum value, and here's dictionary that I'm using to get grouped data:
Dictionary<string, decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => x.Key.OfficeDebitId, x => x.Sum(p => p.Amount));
But I have receiving following error message:
An item with the same key has already been added.
I've tried writing .ToLookup instead of .ToDictionary but that didn't helped me..
Thanks guys
Cheers
If your dictionary has only OfficeDebitId as key then you need to group by only by it:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => p.OfficeDebitId)
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
or use full anonymous object as key:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
Or with value tuple as key:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => (p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod))
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
Why not this:
Dictionary<string, decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => p.OfficeDebitId)
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
You might need it in this way (You can use value tuple):
Dictionary<(string OfficeDebitId, System.DateTime? OfficeDebitDate, Enumerations.PaymentMethod? PaymentMethod), decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => (x.Key.OfficeDebitId, x.Key.OfficeDebitDate, x.Key.PaymentMethod ), x => x.Sum(p => p.Amount));
I want to translate this into lambda syntax and can't seem to get it to work:
Grouping by two columns, select max on a different column, return list of complete complex object.
I am writing more text here to get past the validation on this form. How much text is needed until I am allowed to post this?
_clientpolicies = (from policy in
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
group policy by
new
{
PolicyReference = GetPolicyReference(policy),
PolicyType = policy.ProductInformation.PolicyTypeCode
}
into g
let maxPolicyInception = g.Max(p => p.InceptionDate)
from policyGroup in g
where policyGroup.InceptionDate == maxPolicyInception
select policyGroup).ToList();
I dont think there's a way of doing it in one line. So there's my try :
policyGroups=
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm
.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x => GetPolicyReference(x))
.ThenBy(x => x.ProductInformation.PolicyTypeCode)
.ToList();
var maxPolicyInception = policyGroups.Max(p => p.InceptionDate);
_clientpolicies = policyGroups
.Where(g => g.InceptionDate == maxPolicyInception)
.ToList();
_clientpolicies =
_reply.CommercialInsuredGroupWithPolicyTerm.InsuredWithPolicyTerm.SelectMany(x => x.PolicyTerm)
.Where(x => !(string.IsNullOrWhiteSpace(x.PolicyNumber) && string.IsNullOrWhiteSpace(x.ControlNumber)))
.Where(x => x.Insured.DNBAccountNumber == _client.LookupID)
.GroupBy(x =>
new
{
PolicyReference = GetPolicyReference(x),
PolicyType = x.ProductInformation.PolicyTypeCode
},
(key, g) => g.OrderByDescending(gx => gx.InceptionDate).First()
Is possible to access a parameter variable of a previous condition?
How to do this?
var result = collectionA
.First(a => a.id == 1)
.CollectionB
.SelectMany(b => b.CollectionC)
.Select(c => new { propA = a.id, propC = c.id });
You can write
var result = collectionA
.Where(q => q.id == 1).Take(1) //it will be collection of 1 element
.Select(a => a
.CollectionB
.SelectMany(b => b.CollectionC)
.Select(c => new { propA = a.id, propC = c.id })).First();
or
(new [] { collectionA.First(q => q.id == 1) })
.Select(a => a
....
or just
var a = collectionA.First(q => q.id = 1);
a.Select( .....
The solution based on #Artem's answer:
var result = CollectionA
.Where(a => a.id == 1)
.SelectMany(b =>
b.CollectionB
.SelectMany(c => c.CollectionC)
.Select(c => new { b.id, c.id })
);
I´m trying to bring some Data from SQL but I cant do it with Linq, in T-SQL this Work:
select *
from MTRBatch MB
Inner Join MTR M on MB.Id = M.MTRBatchId
Inner JOIN MTRHeats MH on M.Id = MH.MTRId
LEFT OUTER JOIN Vendor V on MB.VendorId = v.Id
Inner Join Manufacturer MF on MB.ManufacturerId = MF.Id
Where MB.ManufacturerId = 1
AND MH.Heat = 'z01'
I need All the tree but with that filter.
I try this but didnt work :
MTRBatches
.Include(x => x.MTRs.Select(m => m.MTRHeats))
.Include(x => x.Manufacturer)
.Include(x => x.Vendor)
.Where(x => (x.Manufacturer.Id == 1));
.Where(x => x.MTRs.Any(m => m.MTRHeats.Any(h => h.Heat == 'z01')));
This should help; dataContext is the name of your instance of Entity Framework container.
var result = dataContext.MTRBatches
.Join(dataContext.MTRs,
mb => mb.Id,
mtr => mtr.MTRBatchId,
(mb, mtr) => new{ Batch = mb, MTR = mtr })
.Join(dataContext.MTRHeats,
x => x.MTR.Id,
mh => mh.MTRId,
(x, mh) => new{ Batch = x.Batch, MTR = x.MTR, Heat = mh })
.Join(dataContext.Vendors.DefaultIfEmpty(),
x => x.Batch.VendorId,
v => v.Id,
(x, v) => new{ Batch = x.Batch, MTR = x.MTR, Heat = x.Heat, Vendor = v })
.Join(dataContext.Manufacturers,
x => x.Batch.ManufacturerId,
mf => mf.Id,
(x, mf) => new{ Batch = x.Batch, MTR = x.MTR, Heat = x.Heat, Vendor = x.Vendor, Manufacturer = mf})
.Where(x => x.Manufacturer.Id == 1 && x.Heat.Heat == "z01");