Linq To Sql, Sum and main and joined table - sql

My linq query
from report in CustomerDayReports
join payments in CustomerPayments on new { report.CustomerId, report.CurrencyId } equals new { payments.CustomerId, payments.CurrencyId } into j
from j2 in j.DefaultIfEmpty()
group report by new { report.CustomerId, report.CurrencyId } into g1
select new
{
Customer = g1.Key.CustomerId,
Currency = g1.Key.CurrencyId,
Debt = g1.Sum(x => x.Value * x.Amount)
}
Result SQL
SELECT
SUM([t0].[Value] * [t0].[Amount]) AS [Debt],
[t0].[CustomerId] AS [Customer],
[t0].[CurrencyId] AS [Currency]
FROM [CustomerDayReport] AS [t0]
LEFT OUTER JOIN [CustomerPayment] AS [t1]
ON ([t0].[CustomerId] = [t1].[CustomerId]) AND ([t0]. [CurrencyId] = [t1].[CurrencyId])
GROUP BY [t0].[CustomerId], [t0].[CurrencyId]
How modify linq for get next SQL?
*SUM([t0].[Value] * [t0].[Amount])*
to
*T0.SUM([t0].[Value] * [t0].[Amount])* - ISNULL(SUM([T1].Amount)
SELECT
SUM([t0].[Value] * [t0].[Amount]) - ISNULL(SUM([t1].Amount), 0) AS [Debt],
[t0].[CustomerId] AS [Customer],
[t0].[CurrencyId] AS [Currency]
FROM [CustomerDayReport] AS [t0]
LEFT OUTER JOIN [CustomerPayment] AS [t1]
ON ([t0].[CustomerId] = [t1].[CustomerId]) AND ([t0]. [CurrencyId] = [t1].[CurrencyId])
GROUP BY [t0].[CustomerId], [t0].[CurrencyId]

Correct grouping is
group new {report, payments} by new { report.CustomerId, report.CurrencyId } into g
All query is
from report in CustomerDayReports
join payments in CustomerPayments on new { report.CustomerId, report.CurrencyId } equals new { payments.CustomerId, payments.CurrencyId } into j
from payments in j.DefaultIfEmpty()
group new {report, payments} by new { report.CustomerId, report.CurrencyId } into g
select new
{
Customer = g.Key.CustomerId,
Currency = g.Key.CurrencyId,
Debt = g.Sum(x => x.report.Value * x.report.Amount) - ((decimal?) g.Sum(x => x.payments.Amount) ?? (decimal?)0)
}

Related

Convert SQL Query to query in C#

I've currently got the SQL code below:
WITH region_list
AS (SELECT r.StateProvinceRegion,
r.CafeId,
s.Longitude,
s.Latitude,
ROW_NUMBER() OVER(PARTITION BY r.StateProvinceRegion
ORDER BY s.Longitude DESC) AS row_no
FROM CafeAddress r
inner join Restaurant s on s.CafeId = r.CafeId
)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ID,
StateProvinceRegion,
Longitude,
Latitude
FROM region_list
WHERE row_no = 1;
How would I go about adding this query? In my method below I've implemented something similar but I don't understand how to add the WITH clause in.
public VersionResponse GetCafeRegion()
{
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
select new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude };
return new VersionResponse()
{
Data = regionList
};
}
Try the below code once.
public VersionResponse GetCafeRegion()
{
var CafeAddress = new List<CafeAddress>();
var Cafe = new List<Cafe>();
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
group new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude } by cafeAddress.StateProvinceRegion into g
select g;
List<object> finalResult = new List<object>();
int index = 1;
foreach(var gg in regionList)
{
var groupRecord = gg.OrderByDescending(x => x.Longitude).FirstOrDefault();
finalResult.Add(new
{
ID = index++,
groupRecord.StateProvinceRegion,
groupRecord.CafeId,
groupRecord.Latitude,
groupRecord.Longitude
});
}
return new VersionResponse()
{
Data = finalResult
};
}

Entity Framework join query with int array

i have got 3 tables on my database.
---Student---
id - name
---Language---
id - lang
---StudentLanguage---(Common Table)
id - studentId - langId
Students can have more languages. i want to search students with an int[] array values. But not with IN() - Contains(), it must be with and - && operator and this operator take int[] values.
in sql =
`select t1.id, t1.name from Student t1 join StudentLanguage t2
ON(t1.id=t2.studentId) where (t2.langId=1 and t2.langId=3 and t2.langId=5);`
so how can i do this query with Entity Framework? (...where new int[] { 1,3,5 })
This code generate some clumsy sql query...
int[] ids = new[] { 1, 3, 5 };
var acc = from st in db.Students select st;
foreach (var id in ids)
{
int id1 = id;
var res =
from st in db.Students
from lng in st.Language
where lng.Id == id1
select st;
acc =
from a in acc
join st in res on a.Id equals st.Id
select a;
}
acc.ToList();
... sql query :
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Student] AS [Extent1]
INNER JOIN [dbo].[StudentLanguage] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Student_Id]
INNER JOIN [dbo].[StudentLanguage] AS [Extent3] ON [Extent1].[Id] = [Extent3].[Student_Id]
INNER JOIN [dbo].[StudentLanguage] AS [Extent4] ON [Extent1].[Id] = [Extent4].[Student_Id]
WHERE ([Extent2].[Language_Id] = #p__linq__0)
AND ([Extent3].[Language_Id] = #p__linq__1)
AND ([Extent4].[Language_Id] = #p__linq__2)
List<int> langIds = new int[] { 1, 3, 5 }.ToList();
var c = langIds.Count;
var res2 = _context.Students
.Where(x => x.StudentLanguages
.Where(l => langIds.Contains(l.langId)).Select(y => y.langId).Distinct().Count() >= c);
result SQL:
SELECT [t0].[id], [t0].[name]
FROM [dbo].[Student] AS [t0]
WHERE ((
SELECT COUNT(*)
FROM (
SELECT DISTINCT [t1].[langId]
FROM [dbo].[StudentLanguage] AS [t1]
WHERE ([t1].[langId] IN (1, 3, 5)) AND ([t1].[studentId] = [t0].[id])
) AS [t2]
)) >= 3
Use Distinct if StudentLanguages theoretically may have several overlapping bundles StudentId - LangId.
Try something like this...
resultArr = [];
For(int i = 0; i<arr.length; i++) {
var result = db.Student.Where(s=>s.StudentLanguage.langId == arr[i]);
resultArr.append(result);
}
var db = new MyDbContext();
var langIds = new[] { 1, 3, 5 };
IEnumerable<Student> student = from st in db.student select st;
foreach (var item in langIds)
{
student = student.Join(db.StudentLanguage.Where(w => w.langId == item),
st => st.studentId,
stMap => stMap.id,
(st, stMap) => new { Student= stMap, StudentLanguage = st})
.Select(x => x.Student).Distinct();
}
i can do this like that. Maybe foreach can be turn linq and this code can be only one line and a little short.
I try to search how to do it and here is what i come out with:
int[] langIds = new int[] { 1, 3, 5 };
var lang = _context.Languages.Where(x => langIds.Contains(x.id));
var result = _context.Students.Where(x => !lang
.Except(x.StudentLanguages
.Select(y => y.Language)
.Intersect(lang)).Any());
Here i use Except and Intersect linqToSQL extension methods.
It produces this SQL statement:
SELECT [t0].[id], [t0].[name]
FROM [dbo].[Student] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT DISTINCT [t1].[id], [t1].[name]
FROM [dbo].[Language] AS [t1]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT DISTINCT [t3].[id], [t3].[name]
FROM [dbo].[StudentLanguage] AS [t2]
INNER JOIN [dbo].[Language] AS [t3] ON [t3].[id] = [t2].[langId]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[Language] AS [t4]
WHERE ([t3].[id] = [t4].[id]) AND ([t4].[id] IN (#p0, #p1, #p2))
)) AND ([t2].[studentId] = [t0].[id])
) AS [t5]
WHERE [t1].[id] = [t5].[id]
))) AND ([t1].[id] IN (#p3, #p4, #p5))
) AS [t6]
))
Note that i populate languages from database. Unfortunatly you can not use local collections in your query since LinqToSQL don't know how to translate them into SQL. If you do the same thing with local int array or any other collection you will get this exception:
LINQ To SQL exception: Local sequence cannot be used in LINQ to SQL
implementation of query operators except the Contains operator

SQL to LINQ query equivalent

Hello I need to crate linq query from this SQL:
SQL:
select
p.id,
p.Name,
sum(h.Hour)
from
dbo.Hour h
INNER JOIN dbo.ProjectView p ON h.ProjectId = p.Id
WHERE
h.PeopleId = 7999
group by
p.Name, p.Id
LINQ: I tried this but it is not the same:
var query = from hours in _hourRepository.GetAll()
join proj in _projectRepository.GetAll() on hours.ProjectId equals proj.Id
where hours.PeopleId == personId
group hours by new { proj.Id, proj.Name, proj.Flag, hours.Hours } into g
select new PopleProjectsSumDto
{
Id = g.Key.Id,
Name = g.Key.Name,
Flag = g.Key.Flag,
Hours = g.Sum(h => h.Hours)
};
OK i find solution by removing hours from group:
LINQ:
var query = from hours in _hourRepository.GetAll()
join proj in _projectRepository.GetAll() on hours.ProjectId equals proj.Id
where hours.PeopleId == personId
group hours by new { proj.Id, proj.Name, proj.Flag } into g
select new PopleProjectsSumDto
{
Id = g.Key.Id,
Name = g.Key.Name,
Flag = g.Key.Flag,
Hours = g.Sum(h => h.Hours)
};

Query syntax in entity framework

I'm doing a query (see below), but I do not know how to retrieve all data from a select.
var model = new dbContext();
var query = from mp in model.matiere_premiere join req in (from stk in model.stock_mp
join ms in model.matiere_premiere
on stk.matiere_premiere_code equals
ms.code
where stk.date <= DateTime.Today
orderby stk.date descending
select new new { stk.qte, stk.matiere_premiere_code })
on mp.code equals req.matiere_premiere_code
group mp by new { mp.code } into grp
orderby grp.Key
select new
{
grp.Key,
grp.First().designation,
grp.Last().frns
};
The equivalent sql query is:
SELECT matiere_premiere.code,matiere_premiere.designation,
"matiere_premiere.unite, matiere_premiere.frns ,IF(ISNULL(REQ.qte), '0.00', REQ.qte) AS qte
FROM matiere_premiere LEFT JOIN (SELECT qte,matiere_premiere_code FROM stock_mp
JOIN matiere_premiere ON matiere_premiere.code = matiere_premiere_code
WHERE DATE <= CURRENT_DATE() ORDER BY DATE DESC)
AS REQ ON REQ.matiere_premiere_code = matiere_premiere.code
GROUP BY matiere_premiere.code ORDER BY matiere_premiere.code
it's simple, the group is also an enumerator, so you should return
select grp;
then, for each group, you can do a foreach of the values
foreach(var group in query)
{
Console.WriteLine("Key: " + group.Key);
foreach(var v in group)
{
Console.WriteLine("Value: " + v.Property);
}
}

Join Subquery result in Linq

I am posting one more doubt of mine:
Is there a way by which we can use the result of one query and then join the same further just like we do in SQL:
SELECT Applications.* , ApplicationFees.ApplicationNo, ApplicationFees.AccountFundDate1,ApplicationFees.AccountFundDate2 ,ApplicationFees.AccountFundDate3 , ApplicationFees.AccountCloseDate1, ApplicationFees.AccountCloseDate2,ApplicationFees.AccountCloseDate3,
isnull(SUBQRY11.AMNT ,0) as SCMSFEE1R,
isnull(SUBQRY12.AMNT,0) as SCMSFEE2R,
Left Join
(
SELECT ApplicationNo,COUNT(ApplicationNo) AS CNT, SUM(Amount) as AMNT
FROM Payments where (FEETYPE=1 AND FeePosition=1) and (FeeDate>='2011-01-01')
and (FeeDate<='2012-01-01')
GROUP BY ApplicationNo
)SUBQRY11
ON ApplicationFees.ApplicationNo= SUBQRY11.ApplicationNo
Left Join
(
SELECT ApplicationNo,COUNT(ApplicationNo) AS CNT2, SUM(Amount) as AMNT
FROM Payments where (FEETYPE=1 AND FeePosition=2) and (FeeDate>='2011-01-01')
and (FeeDate<='2012-01-01')
GROUP BY ApplicationNo )SUBQRY12 ON ApplicationFees.ApplicationNo=SUBQRY12.ApplicationNo
I want to avoid the same in foreach of the query as that will be quite time consuming.
Yes, you can join sub queries. Like this:
var query = from f in db.ApplicationFees
join sub in (from p in db.Payments
where p.Type == 1 && p.Position == 1 &&
p.Date >= fromDate && p.Date <= toDate
group p by p.ApplicationNo into g
select new {
ApplicationNo = g.Key,
CNT = g.Count(),
AMNT = g.Sum(x => x.Amount)
})
on f.ApplicationNo equals sub.ApplicationNo into feePayments
select new { Fee = f, Payments = feePayments };
But writing it in single query is not very maintainable. Consider to compose your query from sub-queries defined separately:
var payments = from p in db.Payments
where p.Type == 1 && p.Position == 1 &&
p.Date >= fromDate && p.Date <= toDate
group p by p.ApplicationNo into g
select new {
ApplicationNo = g.Key,
CNT = g.Count(),
AMNT = g.Sum(x => x.Amount)
};
var query = from f in db.ApplicationFees
join p in payments
on f.ApplicationNo equals p.ApplicationNo into feePayments
select new { Fee = f, Payments = feePayments };