Select distinct data on query - linq

I've been stuck on my query on select a distinct data..
Assume Datas
Peter
Jose
Joseph
Peter
Juan
Michael
Peter
But they have different ID's (Primary key ID on SQL Table)
Here is what I tried so far
var query = (from a in db.Employees
join b in db.People on a.PersonId equals b.PersonId
where a.IsSeparated != true
select b).Distinct();
and
var query = db.Employees.Join(db.People, x => x.PersonId, y => y.PersonId, (x, y) => new { x, y })
.Where(z => z.x.IsSeparated != true).GroupBy(t => t.y.CompleteName).Select(x => x.FirstOrDefault());
but both query still displaying all data. What I want on my query is if there is a duplicate data make it distinct.
If you guys comment on lambda please explain i'm still learning on how to use it.

You can try with following LINQ :
var query = (from a in db.Employees
join b in db.People on a.PersonId equals b.PersonId
where a.IsSeparated != true
select b).GroupBy(x=> new { x.PersonId}).Select(x=>x.First());

var query = (from a in db.Employees
join b in db.People on a.PersonId equals b.PersonId
where a.IsSeparated != true
select b)
.GroupBy(x=> x.CompleteName)
.Select(grp => grp.Value.First());

Related

How to write this LINQ Query in a better way

I have one Linq Query. When I run the query, Only for 10 records its taking 13 seconds to extract the data to the model. I need to know the query which I wrote is good for performance or not. Please guide me what i am doing wrong.
Code
var stocktakelist = (from a in Db.Stocktakes
select new ExportStock
{
Id = a.Id,
ItemNo = a.ItemNo,
AdminId = (from admin in Db.AdminAccounts where admin.Id == a.Id select admin.Name).FirstOrDefault(),
CreatedOn = a.CreatedOn,
Status = (from items in Db.Items where items.ItemNo == a.ItemNo select items.ItemStatu.Description).FirstOrDefault(),
Title = (from tit in Db.BibContents where tit.BibId == (from bibs in Db.Items where bibs.ItemNo == a.ItemNo select bibs.BibId).FirstOrDefault() && tit.TagNo == "245" && tit.Sfld == "a" select tit.Value).FirstOrDefault() // This line of Query only makes the performance Issue
}
).ToList();
Thanks
The reason this is so slow is because it is running the 3 inner LINQ statements for every item in the outer LINQ statement.
Using LINQ joins will run only 4 queries and then link them together, which is faster.
To find out how to join, there are plenty of resources on the Internet depending on the type of LINQ you are using.
If you're retrieving this data from a SQL server, perhaps consider doing this intensive work in SQL - this is what SQL was designed for and it's much quicker than .NET. EDIT: As highlighted below, the work is done in SQL if using LINQ to SQL/Entities and using the correct join syntax.
I was trying to create the corresponding query with some joins for practice.
I cannot test it and i'm not 100% sure that this query will you get the result
you are hoping for but maybe at least it will give you a hint on how to write
joins with linq.
from a in Db.Stocktakes
join admin in Db.AdminAccounts
on a.Id equals admin.Id
into adminJoinData
from adminJoinRecord in adminJoinData.DefaultIfEmpty( )
join items in Db.Items
on a.ItemNo equals items.ItemNo
into itemsJoinData
from itemsJoinRecord in itemsJoinData.DefaultIfEmpty( )
join title in Db.BibContents
(
from subQuery in Db.BibContents
where subQuery.TagNo == "245"
where subQuery.Sfld == "a"
select subquery
)
on title.BibId equals itemsJoinRecord.BidId
into titleJoinData
from titleJoinRecord in titleJoinData.DefaultIfEmpty( )
select new ExportStock( )
{
Id = a.Id,
ItemNo = a.ItemNo,
AdminId = adminJoinRecord.Name,
CreatedOn = a.CreatedOn,
Status = itemsJoinRecord.ImemStatu.Description,
Title = titleJoinRecord.Value
}
As others have said, you should use Left Outer Joins in your LINQ just as you would if writing it in SQL.
Your query above will end up looking roughly like this once converted (this is untested, but gives the basic idea):
var a = from a in Db.Stocktakes
join admin in Db.AdminAccounts on admin.Id equals a.Id into tmpAdmin
from ad in tmpAdmin.DefaultIfEmpty()
join item in Db.Items on item.ItemNo equals a.ItemNo into tmpItem
from it in tmpItem.DefaultIfEmpty()
join title in Db.BibContents on bib.BibId equals items.BibId into tmpTitle
from ti in tmpTitle.DefaultIfEmpty()
where ti.TagNo == "245"
&& ti.Sfld == "a"
select new ExportStock
{
Id = a.Id,
ItemNo = a.ItemNo,
AdminId = ad == null ? default(int?) : ad.Id,
CreatedOn = a.CreatedOn,
Status = it == null ? default(string) : it.ItemStatus.Description,
Title = ti == null ? default(string) : ti.Value
};
Using lambda expressions your query will look like this:
Db.Stocktakes
.Join(Db.AdminAccounts, a => a.Id, b => b.Id, (a,b) => new { a, AdminId = b.Name })
.Join(Db.Items, a => a.ItemNo, b => b.ItemNo, (a,b) => new { a, Status = b.ItemStatus.Description, BidId = b.BibId })
.Join(Db.BibContents, a => a.BibId, b => b.BibId, (a,b) => new { a, Value = b.Value, TagNo = b.TagNo, Sfld = b.Sfld })
.Where(a => a.TagNo == "245" && a.Sfld == "a")
.Select(a =>
new ExportStock { Id = a.Id,
ItemNo = a.ItemNo,
AdminId = a.AdminId,
CreatedOn = a.CreatedOn,
Status = a.Status,
Title = a.Value
}
).ToList();

Linq - Join results from 2 columns from same table

I would like to join results from a table, to sum up the results from a where condition on 2 different rows, as this code:
var a = (from o in _DB.Services
where (o.description.Contains(searchText) || o.nom.Contains(searchText))
orderby o.date
select new { results = ?????, id = ?????? }).Take(maxResults).ToList();
What can I put, in order to take into account the results=???? and id=???
Thanks
Based on your comment, can't you just do the following?
var a = (from o in _DB.Services
where (o.description.Contains(searchText) || o.nom.Contains(searchText))
orderby o.date
select new
{
results = o.description,
id = o.nom
})
.Take(maxResults)
.ToList();

Combining two tables using linq

i have two linq - sql queries, and im wondering how to join them..
First Query
var ab = from a in Items_worker.getCEAItems()
where a.ProjectCode == lbl_projectCode.Text
select new
{
a.ID
};
Second Query
var j = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID;
First Query would return:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
Second Query would return:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
0000-0000-0000-0000-0000
1111-1111-1111-1111-1111
question is how can i possibly join the two table. Wherein the second query should return all of the records with the same ID found in the first query plus the id containing "0000-0000-0000-0000-0000" second query..
The result should be:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
0000-0000-0000-0000-0000
You can use union to join the both queries, for example split your second query in two with conditions like :
var ab = from a in Items_worker.getCEAItems()
where a.ProjectCode == lbl_projectCode.Text
select new
{
a.ID
};
var j = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID where c.ID.Equals("0000-0000-0000-0000-0000");
var j1 = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID where !(c.ID.Equals("0000-0000-0000-0000-0000"));
var result = ab.Union(j.Union(j1));
Hope this helps..

Joining three tables and using a left outer join

I have three tables. Two of them join equally but one will need to join with a left. I'm finding a lot of code to do this in linq but between two tables only.
Here is the SQL code that I'm trying to re-code within LINQ.
SELECT PRSN.NAME
,CO.NAME
,PROD.NAME
FROM PERSON PRSN
INNER JOIN COMPANY CO ON PRSN.PERSON_ID = CO.PERSON_ID
LEFT OUTER JOIN PRODUCT PROD ON PROD.PERSON_ID = PROD.PERSON_ID;
Here is a snippet of LINQ code that I'm using as a base. I'm just not able to piece together the third table (product in my sample SQL) via LINQ and with a left outer join. The sample is between two tables. Thanks for any tips.
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product{Name = String.Empty, CategoryID = 0})
select new { CatName = category.Name, ProdName = item.Name };
Michael
How about this:
var loj = (from prsn in db.People
join co in db.Companies on prsn.Person_ID equals co.Person_ID
join prod in db.Products on prsn.Person_ID equals prod.Person_ID into prods
from x in prods.DefaultIfEmpty()
select new { Person = prsn.NAME, Company = co.NAME, Product = x.NAME })
EDIT: if you want to do a left outer join on all tables, you can do it like this:
var loj = (from prsn in db.People
join co in db.Companies on prsn.Person_ID equals co.Person_ID into comps
from y in comps.DefaultIfEmpty()
join prod in db.Products on prsn.Person_ID equals prod.Person_ID into prods
from x in prods.DefaultIfEmpty()
select new { Person = prsn.NAME, Company = y.NAME, Product = x.NAME })
Taken from another Stackoverflow thread somewhere, there's a more legible way to do this:
var loj = (from prsn in db.People
from co in db.Companies.Where(co => co.Person_ID == prsn.Person_ID).DefaultIfEmpty()
from prod in db.Products.Where(prod => prod.Person_ID == prsn.Person_ID).DefaultIfEmpty()
select new { Person = prsn.NAME, Company = co.NAME, Product = prod.NAME })
This uses a mix of linq query syntax and lambda syntax to what (I believe is) the best result. There's no copious re-aliasing of identifiers, and it's the most concise way to do this that I've seen.

How do I use subquery, groupby, max, and top in single linqToSql statement?

Using LinqToSql, I need to return a single (L) for the most recent modDate in a join table (CL).
Tables:
L (Lid, meta1, meta2, ...)
CL (Cid, Lid, ModDate)
Here is sql that produces the expected result
SELECT l.*
FROM L l
INNER JOIN (
SELECT TOP 1 cl.Lid, MAX(cl.ModDate) as ModDate
FROM CL cl
INNER JOIN L l ON cl.Lid = l.Lid AND l.meta1 = 5
GROUP BY cl.Lid
ORDER BY MAX(cl.ModDate) DESC
) As m ON l.Lid = m.Lid
Simple enough. The subquery projects us to the ids. The query fetches those records with matching ids.
var subquery = db.L
.Where(L => L.meta1 = 5)
.SelectMany(L => L.CLs)
.GroupBy(CL => CL.Lid)
.OrderByDescending(g => g.Max(CL => CL.ModDate))
.Select(g => g.Key)
.Take(1)
var query = db.L
.Where(L => subquery.Any(id => L.Lid == id))
Reflecting on this further, you can get away from the subquery:
var query = db.L
.Where(L => L.meta1 = 5)
.SelectMany(L => L.CLs)
.GroupBy(CL => CL.Lid)
.OrderByDescending(g => g.Max(CL => CL.ModDate))
.Select(g => g.First().L);
As your provided query, I can interpret into this Linq.
var query = from l in Context.L
join m in (from cl in Context.CL
join l in Context.L on cl.Lid equals l.Lid
where l.meta1 == 5
group new { l.Lid, cl.ModDate } by cl.Lid into grp
select new { Lid = grp.Key, ModDate = grp.Max(g => g.ModDate) } into grp
order by grp.ModDate descending
select grp).Take(1) on l.Lid equals m.Lid
select l;
My SQL-fu isn't fabulous and it's before my first coffee, so I assume "l" in the outer query ends up being a completely different "l" to the one in the subquery?
I think this will do it, but you'll have to try to be sure :) It'll be well worth checking what the generated SQL looks like. If you didn't mind it executing as two queries, of course, it would be somewhat simpler.
// Can't do the "Take(1)" here or it will be executed separately
var subquery = from cl in context.CL
join l in context.L on cl.Lid = l.Lid
where l.meta1 = 5 // could put this in join clause
group cl.ModDate by cl.lid into grouped
order by grouped.Max() descending
select grouped.Key;
// But can take the first result of the join
// This may be simpler using dot notation instead of a query expression
var query = (from l in context.L
join lid in subquery
select l).Take(1);
(EDIT: I wasn't taking the max ModDate before. Doh. Also simplified grouping by using the ID as the key (which it was already) so we only need the ModDate as the group values.)

Resources