I'm new in linq and want to write this query:
var query = from p in behzad.rptost
where p.date.substring(0, 4) == "1395"
-->in this calc sum=p.price_moavaq+price_year
select p;
How can I write that query?
From what I assume you are trying to sum up the price_moavaq field per year.
Furthermore, by the use of the substring I guess your date field isn't of DateTime type but just a string.
So you need to use a groupby:
var query = from p in behzad.rptost
group p by p.date.substring(0, 4) into grouping
select new { Year = p.Key, Sum = p.Sum(x => x.price_moavaq);
In the case that your date field is of DateTime type then just use .Year:
var query = from p in behzad.rptost
group p by p.date.Year into grouping
select new { Year = p.Key, Sum = p.Sum(x => x.price_moavaq);
Related
I'm building a Step Tracking web app at work. I'm working with the latest EF Core. There are three tables I'm interacting with:
wg: WellnessGroup (WellnessGroupId, Name)
wgu: WellnessGroupUser (Look up table: WellnessGroupId, EmployeeId)
wsl: WellnessStepsLog (EmployeeId, StepCount)
What I want is to get all of the WellnessGroups and the total step amount for that group. If there are no steps attached to that group yet, I would like for the NULL value to be 0. I have this SQL statement which gives me the desired data:
SELECT wg.Name, SUM(ISNULL(wsl.StepCount, 0)) AS steps
FROM dbo.WellnessGroup AS wg
LEFT JOIN dbo.WellnessGroupUser AS wgu
ON wgu.WellnessGroupId = wg.Id
LEFT JOIN dbo.WellnessStepsLog AS wsl
ON wsl.EmployeeId = wgu.AzureAdUserId
GROUP BY wg.Name
ORDER BY steps DESC;
And I have managed to throw 2 LINQ expressions together on my controller which is giving me only the WellnessGroups that have steps associated with them and is not giving me the WellnessGroup data if there are no steps:
var query = _dbContext.WellnessGroupUser
.Include(x => x.WellnessGroup)
.Join(_dbContext.WellnessStepsLog, group =>
group.AzureAdUserId, steps => steps.EmployeeId,
(group, steps) => new
{
Steps = steps.StepCount,
Date = steps.TrackedDate,
Group = group.WellnessGroup.Name
}).Where(x => x.Date >= yearToDate).Where(x => x.Date <= endDate);
var stepsByGroup = query
.GroupBy(x => x.Group)
.Select(s => new
{
Group = s.Key,
Date = s.Max(x => x.Date),
Steps = s.Sum(x => x.Steps)
});
One way is to query all WellnessGroups and build the sum inside as a second subquery. Like this:
var query =
db.WellnessGroup.Select(wg => new {
wg.WellnessGroupId,
sum = (int?) wg.WellnessGroupUser
.Sum(wgu => wgu.Employee.WellnessStepsLog.Sum(wsl => wsl.StepCount))
});
Note, that the cast to (int?) is important. Otherwise sum is assumed to be int, which causes an InvalidOperationException if there is no sum for a row.
Another way is to build all the sums first. And then do the outer join with the WellnessGroups:
// sum up all stepcounts
var q1 =
from wgu in db.WellnessGroupUser
from wsl in db.WellnessStepsLog
where wgu.EmployeeId == wsl.EmployeeId
group wsl.StepCount by wgu.WellnessGroupId
into g
select new {WellnessGroupId = g.Key, Sum = g.Sum()};
// join with all WellnessGroups
var q2 =
from wg in db.WellnessGroup
join s in q1 on wg.WellnessGroupId equals s.WellnessGroupId into sj
from sum in sj.DefaultIfEmpty()
select new {wg, sum = (int?) sum.Sum};
EDIT:
Since the OP later asked in the comments how to group by more then one field. Here is an example which groups by WellnessGroup.WellnessGroupId and the month of WellnessStepsLog.TrackedDate. There can be more then one field in GroupBy by placing them in a new { ... }. So the first query creates a line per possible WellnessGroup / Month combination. The second query performs the outer join with WellnessGroup just as before:
var q1 =
from wgu in db.WellnessGroupUser
from wsl in db.WellnessStepsLog
where wgu.EmployeeId == wsl.EmployeeId
group wsl.StepCount by new { wgu.WellnessGroupId, wsl.TrackedDate.Month }
into g
select new {g.Key.WellnessGroupId, g.Key.Month, Sum = g.Sum()};
// join with all WellnessGroups
var q2 =
from wg in db.WellnessGroup
join s in q1 on wg.WellnessGroupId equals s.WellnessGroupId into sj
from sum in sj.DefaultIfEmpty()
select new {wg.WellnessGroupId, Month = (int?) sum.Month, Sum = (int?) sum.Sum};
I have a very simple SQL
SELECT s.shop_code
,SUM(im.amt) sum_amt
,s.cell_no#1 shop_cell
FROM tb_sn_so_wt_mst im
,tb_cm_shop_inf s
WHERE im.shop_code = s.shop_code
GROUP BY s.shop_code, s.cell_no#1)
then i try to code linq
var listResult = from warrantyMaster in listWarrantyMasters2.Records
join shopInfo in listShopInfos
on warrantyMaster.ShopCode equals shopInfo.ShopCode
i don't know group by shop code and cell no and sum atm, any one help me out of this problem
The group by syntax with some examples is explained here group clause (C# Reference) and related links.
Here is the direct translation of your SQL query (of course the field names are just my guess since you didn't provide your classes):
var query = from im in listWarrantyMasters2.Records
join s in listShopInfos
on im.ShopCode equals s.ShopCode
group im by new { s.ShopCode, s.CellNo } into g
select new
{
g.Key.ShopCode,
g.Key.CellNo,
SumAmt = g.Sum(e => e.Amt)
};
You can try this code:
var results = from warrantyMaster in listWarrantyMasters2.Records
from shopInfo in listShopInfos
.Where(mapping => mapping.ShopCode == warrantyMaster.ShopCode )
.select new
{
ShopCode = warrantyMaster.ShopCode,
ATM = listWarrantyMasters2.ATM,
ShellNo = shopInfo.ShellNo
}
.GroupBy(x=> new { x.ShopCode, x.ShellNo })
.Select(x=>
new{
ShopCode = x.Key.ShopCode,
ShellNo = x.Key.ShellNo,
SumATM = x.Sum(item=>item.ATM)
});
How do I translate this SQL function to linq query lambda expression?
SELECT Type, DATEDIFF(day,Expiry_Date,GETDATE()) AS Days
FROM Item
GROUP BY Type, Expiry_Date;
Do I first need to create a function in my database?
from i in db.item
group i by new{
type = i.Type,
eDate = i.Expiry_date
} into grp
select new
{
type = grp.key.Type,
date = grp.key.Expiry.Date.Subtract(DateTime.Now.Date).Days
}
This should work:-
var result = db.Item.GroupBy(x => new { x.Type, x.ExpiryDate })
.Select(x => new
{
Type = x.Key.Type,
Days = (DateTime.Now.Date - x.Key.ExpiryDate).Days
};
I have some data in a List of User defined types that contains the following data:
name, study, group, result, date. Now I want to obtain the name, study and group and then a calculation based onthe result and date. The calculation is effectively:
log(result).where max(date) minus log(result).where min(date)
There are only two dates for each name/study/group, so the result from the maximum data (log) minus the result from the minumum date (log). here is what I have tried so far with no luck:
var result =
from results in sortedData.AsEnumerable()
group results by results.animal
into grp
select new
{
animal = results.animal,
study = results.study,
groupNumber = results.groupNumber,
TGI = System.Math.Log(grp.Select(c => c.volume)
.Where(grp.Max(c=>c.operationDate)))
- System.Math.Log(grp.Select(c => c.volume)
.Where(grp.Min(c => c.operationDate)))
};
Anybody any pointers? Thanks.
It isn't entirely clear how the grouping relates to your problem (what sense does it make to extract a property from a range variable after it has been grouped?), but the part you're having difficult with can be solved easily with MaxBy and MinBy operators, such as the ones that come with morelinq.
var result = from results in sortedData.AsEnumerable()
group results by results.animal into grp
select new
{
animal = grp.Key,
study = ??,
groupNumber = ??,
TGI = Math.Log(grp.MaxBy(c => c.operationDate).volume)
- Math.Log(grp.MinBy(c => c.operationDate).volume)
};
Otherwise, you can simulate these operators with Aggregate, or if you don't mind the inefficiency of sorting:
var result = from results in sortedData.AsEnumerable()
group results by results.animal into grp
let sortedGrp = grp.OrderBy(c => c.operationDate)
.ToList()
select new
{
animal = grp.Key,
study = ??,
groupNumber = ??,
TGI = sortedGrp.Last().volume - sortedGrp.First().volume
};
You have a few syntax problems, you cannot use the results parameter after your into grp line. So my initial attempt would be to change your statement like so
var result =
from results in sortedData.AsEnumerable()
group results by new
{
Animal = results.animal,
Study = results.study,
GroupNumber = results.groupNumber
}
into grp
select new
{
animal = grp.Key.Animal,
study = grp.Key.Study,
groupNumber = grp.Key.GroupNumber,
TGI = System.Math.Log(grp.OrderByDescending(c=>c.operationDate).First().volume)
- System.Math.Log(grp.OrderBy(c=>c.operationDate).First().volume)
};
I am trying to convert the following SQL into a LINQ expression
SELECT COUNT(ID) AS Count, MyCode
FROM dbo.Archive
WHERE DateSent>=#DateStartMonth AND DateSent<=#DateEndMonth
GROUP BY MyCode
and I have been trying to follow this webpage as an example:
Converting SQL containing top, count, group and order to LINQ (2 Entities)
I got this so far but I am stuck on understanding the new part
var res = (from p in db.Archives
where (p.DateSent>= dateStartMonth) && (p.DateSent< dateToday)
group p by p.MyCode into g
select new { ??????MyCode = g.something?, MonthlyCount= g.Count() });
Thanks in advance for helping
UPDATE:
can you explain what g.Key is? I dont understand where that variable came from or what it is referring too? I mean what if I group on 4 different things? How would I refer to each one?
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode, archive.Extra into archiveGrp
select new
{
MyCode = archiveGrp.Key,
Extra = archiveGrp.???
MonthlyCount = archiveGrp.Count()
};
The LINQ statement below should work:
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode into archiveGrp
select new
{
MyCode = archiveGrp.Key,
MonthlyCount = archiveGrp.Count()
};
Notice that the Key property will contain the value of the property that you group on, in this case MyCode.
from p in archive
where p.DateSent >= dateStartMonth && p.DateSent < dateToday
group p by p.MyCode into g
select new { Count = g.Count(), MyCode = g.Key }
produces the same output as your Sql in Linqpad