Find Sum of product of 2 columns in LINQ - c#

Find sum of product of 2 columns in LINQ
I have a list of educationprogram objects with 2 properties NOOfPerson & Hours.
I want a sum of product of 2 properties
SUM[NOOfPersons*Hours]
How can I write a LINQ query for this?
List<educationprogram> edu = (from e in dbContext.educationprograms
where e.YearId == 2015
select e).ToList();
This returns the list of object I have to use. But how can I return SUM[Col1*Col2]?

If the two columns are under the educationprograms table then:
var sum = dbContext.educationprograms.Sum(ep => ep.NoOfPeople * ep.Hours);
you can also add a Where clause:
var sum2 = dbContext.educationprograms.Where(e => e.Year == 2015).Sum(ep => ep.NoOfPeople * ep.Hours);

var edu= from e in dbContext.educationprograms
where e.YearId == 2015
select new
{
sum = e.NoofPersons*e.Hours
}).ToList();
now edu is the list of products of noofperson column and hours column.

Related

Join Error | Unable to create a constant value of type only primitive

Very new with LINQ here.
I have the following data in my table (TableA):
ID Name SubmissionNo
1 Jim A-1
2 Andy A-2
3 Rick A-2
4 Mary A-3
5 Zim A-4
6 Loren A-1
I then need to create a query which will allow me to get from that table, those records which have duplicate submission numbers.
Here's my solution so far (Context is the database context):
var duplicates = (from tbl in Context.TableA.AsNoTracking()
group tbl by tbl.SubmissionNo into grp
select new { count = grp.Count(), submissionNo = grp.Key})
.Where(x => x.count > 1)
.OrderBy(y => y.submissionNo).ToList();
The variable duplicates then contains the record:
count submissionNo
2 A-1
2 A-2
I then write the main query which will allow me to get all the records from TableA which has duplicate submissionNo
var myList = (from tbl in Context.TableA.AsNoTracking()
join dup in duplicates on tbl.SubmissionNo equals dup.submissionNo
select new
{
ID = tbl.ID,
Name = tbl.Name,
SubmissionNo = tbl.SubmissionNo
})
.ToList();
I am then getting an error for the myList query with
Unable to create a constant value of type 'Anonymous Type'. Only primitive types or enumeration types are supported in this context.
I think there must be a better way to do this as from the TableA above, I practically want the following results:
ID Name SubmissionNo
1 Jim A-1
2 Andy A-2
3 Rick A-2
6 Loren A-1
Your first query, slightly modified, has all information you need:
var myList = from tbl in Context.TableA.AsNoTracking()
group tbl by tbl.SubmissionNo into grp
where grp.Count() > 1
from item in grp
select new
{
count = grp.Count(),
submissionNo = grp.Key,
item.Name,
);
The pattern group into grp - from item in grp is a commonly used query pattern to group items and then flatten the group again, while keeping in touch with the group data (like Count() and Key).
Now you don't need the join anymore and the exception doesn't occur. By the way, the exception tells you that EF can only handle joins with collections of primitive types (int etc.), because it has to translate the whole expression into SQL. There's simply no translation for rich objects like TableA.
By the way, the query can be improved by removing the repeated Count():
var myList = from tbl in Context.TableA.AsNoTracking()
group tbl by tbl.SubmissionNo into grp
let count = grp.Count()
where count > 1
from item in grp
select new
{
count = count,
submissionNo = grp.Key,
item.Name,
);
This will generate a more efficient SQL statement containing one COUNT instead of two.
Since Entity Framework does not support joining in-memory collections of objects with database collections, a common workaround for this is to filter using Contains.
First, you need to get the IDs to filter on:
var duplicates = (from tbl in Context.TableA.AsNoTracking()
group tbl by tbl.SubmissionNo into grp
select new { count = grp.Count(), submissionNo = grp.Key})
.Where(x => x.count > 1)
.OrderBy(y => y.submissionNo)
.ToList();
var duplicateIds = duplicates.Select(x => x.submissionNo).ToList();
And then change your query to perform a WHERE...IN instead of a JOIN:
var myList = (from tbl in Context.TableA.AsNoTracking()
where duplicateIDs.Contains(tbl.SubmissionNo)
select new
{
ID = tbl.ID,
Name = tbl.Name,
SubmissionNo = tbl.SubmissionNo
})
.ToList();

select rows whose sum greater than 0 using Linq

I need to do, for example: Select customers whose total Sum of Amount is greater than 0. I tried below code and with reference to this result trying fetch data. but not getting Proper result.
var query = (from a in saleList
group a by a.Cust_Ledger_Entry_No into groups
select groups.Sum( s => s.Amount) > 0).ToList();
I did above query.Now I need data which satisfying above condition.Please help me.
You need a Where
var query = from a in saleList
group a by a.Cust_Ledger_Entry_No into g
where g.Sum( s => s.Amount) > 0
select new { Cust_Ledger_Entry_No = g.Key, SumAmount = g.Sum( s => s.Amount) };
I need result like, customers whose sum of amount greater than 0
with all columns
If a is the customer and you need to select all you can use this query:
var query = from a in saleList
group a by a.Cust_Ledger_Entry_No into g
where g.Sum( s => s.Amount) > 0
from customer in g // flatten each group
select customer;

Linq to sql calculating a percentage of a group of items in query

New to Linq to SQL and novice in SQL. First post so please be gentle.
I have something similar to the following table I am querying into a dataGridView based on a date range in C#.
HeatNumber ChargeNumber Weight DOB
1 1 500 8/26/15
1 2 3500 8/26/15
1 3 2200 8/26/15
2 1 2000 8/27/15
2 2 1100 8/27/15
var query = from SU in dct.GetTable<ScrapInCharge>()
where ((SU.DOB >= dateTimePicker2.Value.Date) &&
(SU.DOB <= dateTimePicker1.Value.Date))
orderby SU.HeatNumber descending
select SU;
scrapInChargeBindingSource.DataSource = query;
I need to add a column that shows the percentage of the total HeatNumber weight that each ChargeNumber makes up. I did figure how to get the total weight of each heat by HeatNumber.
var TotalHeatWgt = from a in dct.ScrapInCharges
where ((a.DOB >= dateTimePicker2.Value.Date) &&
(a.DOB <= dateTimePicker1.Value.Date))
group a.Weight by a.HeatNumber
into b
select new { HeatNumber = b.Key, TotalWgt = b.Sum() };
I am currently stuck on how to combine this into a single C# query inserting a % of Heat column after the weight column. Can this be done or would I need to add an unbound column to the dataGridView % of Heat and iterate over the rows using my return values of the TotalHeatWgt query?
Simple attempt:
var results = data.Select(d => new {
d.HeatNumber,
d.ChargeNumber,
d.Weight,
Percent = 100.0 * d.Weight / data.Where(dd => dd.HeatNumber == d.HeatNumber).Sum(dd => dd.Weight)
});
or
from row in data
select new {
row.HeatNumber,
row.ChargeNumber,
row.Weight,
Percent = 100.0 * row.Weight / (from innerRow in data
where innerRow.HeatNumber == row.HeatNumber
select innerRow.Weight
).Sum()
};
The one below will be more performant (at least in memory, I'm not sure if it'll be better in SQL):
var results = data.GroupBy (d => d.HeatNumber)
.SelectMany (grp => grp.Select(row => new {
row.HeatNumber,
row.ChargeNumber,
row.Weight,
Percent = 100.0 * row.Weight / grp.Sum(dd => dd.Weight)
})
);
And with query syntax:
from row in data
group row by row.HeatNumber into grp
from innerRow in grp
select new {
innerRow.HeatNumber,
innerRow.ChargeNumber,
innerRow.Weight,
Percent = 100.0 * innerRow.Weight / grp.Sum(dd => dd.Weight)
};
They both print this result:
HeatNumber ChargeNumber Weight Percent
1 1 500 8.06451612903226
1 2 3500 56.4516129032258
1 3 2200 35.4838709677419
2 1 2000 64.5161290322581
2 2 1100 35.4838709677419
Is that what you're after? I've omitted the filtering by date just for simplicity, since the actual problem comes after that

LINQ error - The method 'Sum' is not supported

I am having following linq -
var quantity = (from p in context.StoreInventory
where p.BookId== BookId
&& p.StoreAddress == StoreAddress
select p).Sum(i => i.Quantity);
I am getting error -
The method 'Sum' is not supported
Can anyone tell me the reason and required changes.
var quantity = (from p in context.StoreInventory
where p.BookId== BookId
&& p.StoreAddress == StoreAddress
select p.Quantity).Sum();
This should work - the sum is performed on 'Quality' column, which is taken using select statement. That's because Sum(expression) is not supported by LINQ to Entities, but standard Sum() is.
Whole work should be done by database, so no rows will be retrieved by application - just single number.
Use Enumerable.ToList before you call Sum to convert the query to collection.
var quantity = (from p in context.StoreInventory
where p.BookId== BookId
&& p.StoreAddress == StoreAddress
select p).ToList().Sum(i => i.Quantity);
Edit: This will bring all the row and will apply the sum which is not efficient way of doing. As you need to sum up quantity you can select quanity instead of row.
var quantity = (from p in context.StoreInventory
where p.BookId== BookId
&& p.StoreAddress == StoreAddress
select p.Quantity).Sum();

How to return value from 2 tables in one linq query

please consider this table:
PK_Id Number Year Month Value
-------------------------------------------------------------------------
1 1 2000 5 100000
410 4 2000 6 10000
8888 1 2001 5 100
I Id=8888 and now I want to first select record with Id=8888 and second select previos year of that record*(I mean Id=1)*. How I can do this with linq and one query.
basically we have some queries that first it should find a value from a table (that may be not PK) and find Corresponding records in another tables. How I can do this with linq and one reference to database.
thanks
from a in Record
where a.PK_Id == 8888
from b in Record
where b.Number == a.Number && b.Year == a.Year - 1
select new { Current = a, Previous = b }
or
Record
.Where(a => a.PK_Id == 888)
.SelectMany(a =>
Record
.Where(b => b.Number == a.Number && b.Year == a.Year - 1)
.Select(b => new { Current = a, Previous = b })
If I understand your question right, then you need to filter the data of one table and join two tables.
You can join the tables and filter your data
var query = from c in Table1
join o in Table2 on c.Col1 equals o.Col2
where o.Col3 == "x"
select c;
or you can filter your data from one table and then join the tables (result will be the same)
var query = from c in Table1.Where(item => item.Col3 == "x")
join o in Table2 on c.Col1 equals o.Col2
select c;

Categories