Join with last record of details table - c#

Please consider these two tables in my database:
Header:
Id Name
-------------------------------
1 London
2 Berlin
3 Paris
and Details:
Id HeaderId Amount YearMonth
--------------------------------------------------------------------
1 1 1000 2010-01
2 1 2000 2010-05
3 2 3000 2015-04
4 2 2700 2017-12
5 2 4500 2016-10
6 2 7000 2011-09
7 1 3000 2009-05
I want Header records with related Last Details record. For example:
HeaderId HeaderName Amount
----------------------------------------------------
1 London 2000
2 Berlin 2700
3 Paris Null
I wrote this query for Inner Join version (But I want Outer Join version):
from h in Header
join d in Details
on h.Id equals d.HeaderId
select new
{
HeaderId = h.Id,
HeaderName = h.Name,
Amount = (Details.Where(k=>k.HeaderId == h.Id).OrderBy(m=>m.YearMonth).LastOrDefault() == null ? null : Details.Where(k=>k.HeaderId == h.Id).OrderBy(m=>m.YearMonth).LastOrDefault().Amount,
}
and I got this error:
System.NotSupportedException: LINQ to Entities does not recognize the method 'Details.LastOrDefault()Details' method, and this method cannot be translated into a store expression.
How can I get above result?
thanks

This query should return desired result:
from h in Header
from d in Details.Where(d => d.HeaderId == h.Id)
.OrderByDescending(d => d.YearMonth)
.Take(1)
.DefaultIfEmpty()
select new
{
HeaderId = h.Id,
HeaderName = h.Name,
Amount = d.Amount
}

You should change your code as :
Amount = Details.Where(k=>k.HeaderId == h.Id).OrderByDescending(m => m.YearMonth).FirstOrDefault(o=>o.Amount);

Related

How to apply self join in Linq Query?

Books Table
Id VendorId ASIN Price
-- -------- ---- ------
1 gold123 123 10
2 sil123 123 11
3 gold456 456 15
4 gold678 678 12
5 sil456 456 12
6 gold980 980 12
I want to write a linq query which will return me rows for which corresponding to every gold if sil vendor id not exist. The last three digit of vendor Id is corresponding ASIN column in that row.
Ex- For gold123 corresponding sil123 exist so that row will not be returned but for gold678 and gold980 corresponding sil not exist. So those rows will be returned.
I tried following
var gold = _repository.Query<Books>().Where(x =>
x.VendorId.Contains("gold"))
.OrderBy(x => x.Id).Skip(0).Take(500).ToList();
var asinsForGold = gold.Select(x => x.ASIN).ToList();
var correspondingSilver = _repository.Query<Books>().Where(x =>
x.VendorId.Contains("sil")
&& asinsForGold.Contains(x.ASIN)).ToList();
var correspondingSilverAsins = correspondingSilver.Select(x => x.ASIN).ToList();
var goldWithoutCorrespondingSilver = gold.Where(x =>
!correspondingSilverAsins.Contains(x.ASIN));
Can We apply self join or better way to get result only in one query instead of two query and several other list statement.
It's just another predicate, "where a corresponding silver vendor doesn't exist":
var goldWoSilver = _repository.Query<Books>()
.Where(x => x.VendorId.Contains("gold"))
.Where(x => !_repository.Query<Books>()
.Any(s => s.ASIN == x.ASIN
&& s.VendorId.Contains("sil"))
.OrderBy(x => x.Id).Skip(0).Take(500).ToList();
In many cases this is a successful recipe: start the query with the entity you want to return and only add predicates. In general, joins shouldn't be used for filtering, only to collect related data, although in that case navigation properties should be used which implicitly translate to SQL joins.
See if it helps -
var goldWithoutCorrespondingSilver = from b1 in books
join b2 in books on b1.ASIN equals b2.ASIN
where b1.VendorId.Contains("gold")
group b2 by b1.VendorId into g
where !g.Any(x => x.VendorId.Contains("sil"))
select g.FirstOrDefault();
What I have done is -
Selected records with matching ASIN
Grouped them by VendorID
Selected ones which do not have sil

LINQ Query multiple orderby of joined tables

I have following LinQ query
var CGTABLE = (from cg in DbContext.CGTABLE
join tcg in DbContext.TCGTABLE on new { cg.CGroupId } equals new { tcg.CGroupId }
where tcg.TId == TId
select new {
CGroupId = cg.CGroupId,
CGroupCode = cg.CGroupCode,
Description = cg.Description,
C = cg.C,
DisplayOrder = cg.DisplayOrder
}).ToList();
CGTABLE = CGTABLE.OrderBy(g => g.DisplayOrder).ThenBy(g => g.C.OrderBy(c => c.CCode)).ToList();
which runs fine, but it is not doing second orderby using ThenBy ThenBy(g => g.C.OrderBy(c => c.CCode) What am I missing?
Sample data for better understanding.
Data in Tables
2
1
2
4
3
1
4
5
2
1
3
3
1
Should output after both outer and inner list ordered by
1
1
2
3
4
2
1
2
4
5
3
1
3
But Currently it is showing
1
4
5
2
1
2
1
2
4
3
3
3
1
You didn't want to order the main list, you are looking for a way to order inner list inside of outer one, I think.
So below code will do it for you:
var CGTABLE = (
from cg in DbContext.CGTABLE
join tcg in DbContext.TCGTABLE on new { cg.CGroupId } equals new { tcg.CGroupId }
where tcg.TId == TId
select new {
CGroupId = cg.CGroupId,
CGroupCode = cg.CGroupCode,
Description = cg.Description,
C = cg.C.OrderBy(x => x.CCode),
DisplayOrder = cg.DisplayOrder
}).ToList();
CGTABLE = CGTABLE.OrderBy(g => g.DisplayOrder).ToList();

get all the latest entries from table linq

I have two tables like below: (date format : mm/dd/yyyy)
Parameter master table:
Id Parameter
1 ST
2 GP
3 Interest
4 CC
And Second TaxValue table :
Date ParameterId Value
1/1/2017 1 4
2/1/2017 1 4.5
1/15/2017 2 15
3/20/2017 2 20
3/21/2017 3 18
4/28/2017 3 20
1/1/2017 4 10
I want to write a linq query to get all the latest parameters values from the date specified.
Desired Result: (if I want to get latest entries for today)
Date Parameter Value
2/1/2017 ST 4.5
3/20/2017 GP 20
4/28/2017 Interest 20
1/1/2017 CC 10
Please help!!
User OrderByDescending
var result = from n in table
group n by n.Value into g
select g.OrderByDescending(t=>t.Date).FirstOrDefault();
You can do a join on the latest TaxValue record like this:
var qry = (from pm in parameterMaster
from tax in taxValue.Where(t => t.ParameterId == pm.Id)
.OrderByDescending(t => t.Date)
.Take(1)
.DefaultIfEmpty()
select new {
date = tax.Date,
parameter = pm.Name,
value = tax.Value
});
var results = qry.ToList();
You can use this query: (I tested it and it worked properly)
using (testEntities db = new testEntities())
{
var res = from element in
(from p in db.Parameters
join t in db.TaxValues on p.Id equals t.ParameterId
select new { Date = t.Date, Parameter = p.Parameter1, Value = t.Value, ParameterId = t.ParameterId }).ToList()
group element by element.ParameterId
into groups
select groups.OrderBy(p => p.Value).Last();
}
Result

convert an sql query into linq to entities method based

i have got this query in sql server server that do what i want..
how can i convert it to linq
select t1.IDHardware,h.DescricaoHardware
from dbo.ProcessoHardware t1
INNER JOIN
(select t2.IDHardware, max(t2.IDProcessoHardware) as maxVisit
from dbo.ProcessoHardware t2
group by t2.IDHardware,t2.IDProcesso) v ON
v.maxVisit = t1.IDProcessoHardware JOIN dbo.Hardware h ON t1.IDHardware=h.IDHardware
where t1.Estado=1 AND IDProcesso=1
this is where i am now...but i am unable to figure it past this point..
var ProcHardware = (from procHardware in db.ProcessoHardwares
where procHardware.IDProcesso == IDProcesso
select new { procHardware.IDHardware, procHardware.IDProcessoHardware, procHardware.IDProcesso, procHardware.Estado } into x
group x by new { x.IDHardware, x.IDProcesso, x.IDProcessoHardware, x.Estado } into t
let Max = t.Max(g => g.IDProcessoHardware)
select new { IDHardware = t.Key.IDHardware, Estado = t.Key.Estado, t.Key.IDProcesso,IDProcessoHardware=t.Key.IDProcessoHardware,cMax=Max }).ToList().Where(t => t.Estado == 1 && t.IDProcesso == IDProcesso && t.IDProcessoHardware==Max).Select(c => new VMProcessoChooseHardware
{
IDHardware = c.IDHardware
});
i have got this table that relates the Table hardware with a table Process.. this table is called processHardware. this table is discribed by: IDProcessHardware IDProcess IDHardware State
the field state can have 3 states (1-Insert, 2-Remove,3-Substitute).. so i can i have this:
IDProcessHardware IDProcess IDHardware State
1 10 1 1
2 10 2 1
3 10 1 2
4 10 1 1
5 20 1 1
what i want to get is get the IDHardware that were inserted but not removed from process.
so by giving the IDProcess = 10 i want to get the hardware with the hardware ids 1 and 2..
IDProcessHardware IDProcess IDHardware State
1 10 1 1
2 10 2 1
3 10 1 2
4 20 1 1
in the table above by giving the IDProcess 10 , it should give me the Hardware ids 2.
Thanks in advance...
After a lot of trial and error, and a lot of search i found this link
http://jetmathew.wordpress.com/2014/01/21/select-latest-record-from-recordset-using-sql-and-linq/
the guy was trying something similar to what i want..
so i pick the linq query and transform it..
this is what i have now
var ProcHardware = (from a in db.ProcessoHardwares
group a by new { a.IDHardware, a.IDProcesso } into latest
join b in db.ProcessoHardwares on new { dt = latest.Max(itm => itm.IDProcessoHardware) } equals new { dt = b.IDProcessoHardware }
select new { ID = b.IDHardware, Estado=b.Estado,IDProcesso=b.IDProcesso }).ToList().Where(t => t.Estado == 1 && t.IDProcesso == IDProcesso ).Select(c => new VMProcessoChooseHardware
{
IDHardware = c.ID
});
it still need the rest the information discribing the hardware like the serial number , or the description.
i will post here the complete query..

linq query for finding total leave group by leave type

i have 1 employee leave table which contain records like this:
empid leave_type Leave_from Leave_to leave_taken status
1 annual leave 3-3-2014 4-3-2014 2 approved
1 annual leave 5-3-2014 6-3-2014 2 approved
1 sick leave 10-3-2014 11-3-2014 2 approved
1 sick leave 12-3-2014 13-3-2014 2 approved
1 Casual leave 19-3-2014 20-3-2014 2 approved
1 Casual leave 22-3-2014 23-3-2014 2 approved
now i want to calculate total leave taken by particular employee by leave type of march month only whose status is approved like as shown in below:
leave_type leave_taken
annual leave 4
sick leave 4
casual leave 4
i have written query like this:
var data = (from r in context.emp_leaves
where r.Emp_id == empid && r.status == "Approved"
group r by new
{
r.Emp_id,r.leave_type
} into g
select new
{
leave_taken = g.Sum(x => x.leave_taken)
});
but it is showing wrong output.
can anyone provide me linq query for this???
Since you are filtering by Emp_id you do not need to group on it
var data = (from r in context.emp_leaves
where r.Emp_id == empid && r.status == "Approved"
group r by r.leave_type into g
select new
{
leave_type = g.Key,
leave_taken = g.Sum(x => x.leave_taken)
});

Categories

Resources