Linq left joining with non trivial condition - linq

This is fine, it produces a left join
var q =
from c in categories
join p in products
on c equals p.Category into ps
from p in ps.DefaultIfEmpty()
select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };
But what about if I wanted to do something like this:
...
on p.date between c.startdate and c.enddate
...

var q =
from c in categories
join p in products
on c equals p.Category into ps
from p in ps.DefaultIfEmpty()
where p.date >= c.startdate && p.date <= c.enddate
select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };

Related

Left join with LINQ with entityframework

I try to make a left query with linq:
public IQueryable<Mutatie> GetMutaties()
{
var query = (from m in context.Mutatie
join d in context.tblDienstverband on m.fkDienstVerbandID equals d.DienstverbandID
join med in context.tblMedewerker on d.fkMedewerkerID equals med.MedewerkerID
where med.fkKlantID == this.klantId
select m).Include(d => d.fkDienstVerbandID);
return query;
}
But how to make this to have a left query?
Thank you
I have it now like this:
var query = (from m in context.Mutatie
join d in context.tblDienstverband on m.fkDienstVerbandID equals d.DienstverbandID into grp
from d in grp.DefaultIfEmpty()
join med in context.tblMedewerker on d.fkMedewerkerID equals med.MedewerkerID into grp1
from med in grp.DefaultIfEmpty()
where med.fkMedewerkerID == this.klantId
select new { m, d, med });
return query;
It should like this:
NOTE: d and med are null if no row match
public IQueryable<Mutatie> GetMutaties()
{
var query = (from m in context.Mutatie
join d in context.tblDienstverband on m.fkDienstVerbandID equals d.DienstverbandID into grp
from d in grp.DefaultIfEmpty()
join med in context.tblMedewerker on d.fkMedewerkerID equals med.MedewerkerID into grp_med
from med in grp_med.DefaultIfEmpty()
where med.fkKlantID == this.klantId
//select new { m, d, med };
select m;
return query;
}

Linq FirstOrDefault List inside a query

I have this linq query
var numberGroups =
from n in VISRUBs.Where(a => a.VISANA.VISITE.DATEVIS <= d && a.VISANA.VISITE.PANUM == p)
group n by n.RUBRIQUE into g
select new {
RemainderCHAPLIB = g.Key.ANALYSE.CHAPITRE.LIBELLE,
RemainderLIB = g.Key.LIBELLE,
RemainderRUNUM = g.Key.RUNUM,
vals = from vlist in g.OrderByDescending(a=>a.VISANA.VISITE.DATEVIS)
select vlist.VALEUR
};
which gives me this result in Linqpad
What I want is to select the first and second item from the last field (vals) which is a List<string>.
I have tried this:
var numberGroups =
from n in VISRUBs.Where(a => a.VISANA.VISITE.DATEVIS <= d && a.VISANA.VISITE.PANUM == p)
group n by n.RUBRIQUE into g
select new {
RemainderCHAPLIB = g.Key.ANALYSE.CHAPITRE.LIBELLE,
RemainderLIB = g.Key.LIBELLE,
RemainderRUNUM = g.Key.RUNUM,
vals = from vlist in g.OrderByDescending(a => a.VISANA.VISITE.DATEVIS)
select vlist.VALEUR
};
var lst = from n in numberGroups
select new
{
RemainderCHAPLIB = n.RemainderCHAPLIB,
RemainderLIB = n.RemainderLIB,
RemainderRUNUM = n.RemainderRUNUM,
VAL = n.vals.FirstOrDefault()
};
but it didn't work, I got an exception:
Dynamic SQL ErrorSQL error code = -104Token unknown - line 54, column 1OUTER
found it !
var lst = from n in numberGroups.ToList()
select new
{
RemainderCHAPLIB = n.RemainderCHAPLIB,
RemainderLIB = n.RemainderLIB,
RemainderRUNUM = n.RemainderRUNUM,
VAL = n.vals.FirstOrDefault(),
ANT = n.vals.Skip(1).FirstOrDefault()
};

get the sum of the maxs group by

I have this table
EquipmentId Value Date
1 2 11/04/2013
1 1 11/04/2013
2 3 11/04/2013
2 2 10/04/2013
2 5 10/04/2013
3 1 10/04/2013
3 3 11/04/2013
I want to group these items by date, and have a dictionary with the date as a key and the sum of the maxs of the all equipments values in that day
the result would be like this
[10/04/2013: 6] // 6 = 5 (as the max of values of the the equipmetId 2) + 1 (as the max of values of the the equipmetId 3)
[11/04/2013: 5] // 5 = 2(as the max of values of the the equipmetId 1) + 3(as the max of values of the the equipmetId 3)
I managed to make the query to get this without the sum, meaning for only one equipment.
var consumptionValues = (from c in context.ConsumptionSet
join pi in context.PropertiesInstanceSet on c.PropertiesInstanceID equals pi.PropertiesInstanceID
join ep in context.EquipmentPropertiesSet on pi.EquipmentPropertiesID equals ep.EquipmentPropertiesID
join e in context.EquipmentSet on ep.EquipmentID equals e.EquipmentID
where (e.EquipmentID == equipmentId && pi.ProprietesName == ProprietesName.Energy && c.Date <= DateTime.Now && c.Date >= firstDayDate)
group c by SqlFunctions.DatePart("weekday", c.Date) into grp
select new
{
dayOfWeek = (DayOfWeek)grp.Key.Value - 1,
value = grp.Max(c => c.Value),
}).ToDictionary(c => c.dayOfWeek.ToString(), c => c.value);
It's the complete query with all the joins, in the example I just gave a simplified example.
Is it possible to do this in one single query ?
I have to say I'm not sure it will work, but you should give it a shot:
var consumptionValues = (from c in context.ConsumptionSet
join pi in context.PropertiesInstanceSet on c.PropertiesInstanceID equals pi.PropertiesInstanceID
join ep in context.EquipmentPropertiesSet on pi.EquipmentPropertiesID equals ep.EquipmentPropertiesID
join e in context.EquipmentSet on ep.EquipmentID equals e.EquipmentID
where (e.EquipmentID == equipmentId && pi.ProprietesName == ProprietesName.Energy && c.Date <= DateTime.Now && c.Date >= firstDayDate)
group new { c, e } by SqlFunctions.DatePart("weekday", c.Date) into grp
select new
{
dayOfWeek = (DayOfWeek)grp.Key.Value - 1,
value = grp.GroupBy(i => i.e.EquipmentID).Sum(g => g.Max(i => i.c.Value)),
}).ToDictionary(c => c.dayOfWeek.ToString(), c => c.value);

How to write order by in linq

This code output is like this
a 1
b 12
I wont to get out put like this
b 12
a 1
Query:
var x1 = (from v in db3.VoteRecords
join v2 in db3.Partis on v.PartiID equals v2.ID
where v.ProvinceID == (int)cmbProvience.SelectedValue
&& v.DistrictID == (int)cmbDistrict.SelectedValue
group v by new { v2.PartiName } into g
select new
{
Parti = g.Key.PartiName,
Votes = (from vt in g
select g.Key.PartiName).Count()
});
dataGridView1.DataSource = x1;
You can add this at the end
{
Parti = g.Key.PartiName,
Votes = (from vt in g
select g.Key.PartiName).Count()
}).OrderByDescending(l =>l.Parti);
If you want to order by the Votes column. Do this:
{
Parti = g.Key.PartiName,
Votes = (from vt in g
select g.Key.PartiName).Count()
}).OrderByDescending(l =>l.Votes);
Or if you first want to order by Parti and then by Votes do this:
{
Parti = g.Key.PartiName,
Votes = (from vt in g
select g.Key.PartiName).Count()
}).OrderByDescending(l =>l.Parti).ThenByDescending (l =>l.Votes);
Or if you first want to order by Votes and then by Parti do this:
{
Parti = g.Key.PartiName,
Votes = (from vt in g
select g.Key.PartiName).Count()
}).OrderByDescending(l =>l.Votes ).ThenByDescending (l =>l.Parti);

Convert to Lambda expression

I have the following expression
var q = from c in D1
join dp in
(from e in E1
group e by e.ID into g
select new { ID = g.Key, Cnt = g.Count() })
on c.ID
equals dp.ID
into dpp from v in dpp.DefaultIfEmpty()
select new { c.ID, Cnt= v.Cnt ?? 0 };
How can i convert this to Lambda expression?
Here's one way to go. This kind-of matches the above.
var subquery = E1
.GroupBy(e => e.Id)
.Select(g => new { ID = g.Key, Cnt = g.Count()});
//.ToList();
var q = D1
.GroupJoin(
subquery,
c => c.ID,
dp => dp.ID,
(c, g) => new {ID = c.ID, Cnt=g.Any() ? g.First().Cnt : 0 }
)
After refactoring, I came up with this:
var q = D1
.GroupJoin(
E1,
d => d.ID,
e => e.ID,
(d, g) => new {ID = d.ID, Cnt = g.Count()}
);
For comparision, the query comprehension form is:
var q = from d in D1
join e in E1 on d.ID equals e.ID into g
select new {ID = d.ID, Cnt = g.Count()};
Why would you want to convert it?
For complex queries like this one the query syntax you have used here is invariably clearer.

Resources