Linq to Sql selecting last row in a joined table - c#

I am trying to select multiple table values using linq to sql
This is the code I wrote:
var query = (from p in context.Personel
join y in context.PerLanguage on p.ID equals y.ID
where p.Resign == false && p.KGBT > new DateTime(2012,1,15)
select new{ p.ID,p.NameSurname, y.EarnedDate,y.Degree}).ToList();
PerLanguage has a foreignkey "ID" to Personel. So PerLanguage table can have 2 or more data that has the same ID. I am expecting this piece of code to return me a List of items having the "last" entered Language data of different people.
What is the best way to do it?

try the following query.. basically we make the join, get the flat results, group it by id and descending sort the results within an ID and select the first record in every grouped result.
var results = context.Personel.Where(p => !p.Resign && p.KGBT > new
DateTime(2012,1,15)).Join(context.PerLanguage, p => p.ID, pl => pl.ID, (p, pl) =>
new { p.ID, p.NameSurname, pl.EarnedDate, pl.Degree }).GroupBy(r => r.ID)
.Select(g => g.OrderByDescending(r => r.EarnedDate).First()).ToList();

Related

Convert MSSQL Query to Lambda Expressions or LINQ. Grouping Sum and Sorting

I have a SQL Query to extract sorted data by sum of a column value. I have a table named CustomerPoint and It has 2 columns named CusTomerID and Point , I want to extract the person with the highest SUM of points. Here is my SQL Query and it runs properly. But I need to execute it in EF6.3 with LambdaExpressions or Linq queries.
SELECT SUM(Point) AS POINTS, CustomerID FROM CustomerPoint AS POINTS GROUP BY CustomerID ORDER BY POINTS
Thank you for your help!
Something like this:
from p in context.Points
group p by p.CustomerID into gr
select new { CustomerID = gr.Key, POINTS = gr.Sum(c=>c.Point) } into re
orderby re.POINTS
Please try this.
from cp in db.CustomerPoints
Group cp by cp.CusTomerID into cpg
select new { CusTomerID = cpg.Key, Points = cpg.Sum(c => c.Point)}
orderby cpg.Points
And lambda form for diversity:
var query = youContext.CustomerPoints
.GroupBy(x => x.CustomerID)
.Select(x => new { Points = x.Sum(y => y.Point),
CustomerID = x.Key })
.OrderBy(x => x.Points);

SQL left outer join, groupby & orderby to LINQ method query or method syntax

The main objective is to return a list of ingredients in a sorted order according to popularity (which is indicated by how many people have as their favorite a particular ingredient). The SQL equivalent is below:
select distinct COUNT(PersonalInfoes.FavoriteIngredient_ID) as NoUsing,
Ingredients.Name
from PersonalInfoes right join Ingredients
on PersonalInfoes.FavoriteIngredient_ID = Ingredients.ID
group by Ingredients.Name
order by NoUsing desc
What is the equivalent SQL query of method syntax that will produce the same result as above?
The closest I've got is this:
from i in db.Ingredients
join p in db.PersonalInfos on i.ID equals p.FavoriteIngredient.ID into ing
from p in ing.DefaultIfEmpty()
group i by i.Name into g
from p in g
orderby g.Count() descending
select new { Name = g.Key, Count = g.Count() }.Name;
Your query does a left outer join to include ingredients with no favorites. The problem is, for each ingredient with no favorites, you are counting the single value that gets produced by DefaultIfEmpty(). You can exclude the default values when counting like this:
orderby g.Count(x => x != null) descending
You actually don't have to perform a left join. You can just sum the counts of the groups from your group join:
from i in db.Ingredients
join p in db.PersonalInfos on i.ID equals p.FavoriteIngredient.ID into faves
group faves.Count() by i.Name into faveCounts
let count = faveCounts.Sum()
orderby count descending
select new { Name = faveCounts.Key, Count = count };
A subjective problem with your code is it's very confusing with all of the group by and from clauses. If you find this to be an issue, you can try using more descriptive names, using subqueries, or using method syntax.
Edit: Here is a method syntax version. It is not a direct conversion from the query syntax version because that would be quite ugly.
db.Ingredients
.GroupJoin(db.PersonalInfos,
i => i.ID,
p => p.ID,
(i, g) => new { i.Name, FaveCount = g.Count() })
.GroupBy(x => x.Name,
(key, grp) => new { Name = key, Count = grp.Sum(y => y.FaveCount) })
.OrderByDescending(x => x.Count);

how to convert T-SQL Query to linq

i have 4 table in SQL: DocumentType,ClearanceDocument,Request, RequestDocument.
i want when page load and user select one request, show all Document Based on clearanceType in RequestTable and check in RequestDocument and when exist set is_exist=true
I have written this query with SqlServer Query Editor for get result this Scenario but i can't convert this Query to Linq
select *,
is_Orginal=
(select is_orginal from CLEARANCE_REQUEST_DOCUMENT
where
DOCUMENT_ID=a.DOCUMENT_ID and REQUEST_ID=3)
from
DOCUMENT_TYPES a
where
DOCUMENT_ID in
(select DOCUMENT_ID from CLEARANCE_DOCUMENTS dt
where
dt.CLEARANCE_ID=
(SELECT R.CLEARANCE_TYPE FROM CLEARANCE_REQUEST R
WHERE
R.REQUEST_ID=3))
i write this Query in linq but not work
var list = (from r in context.CLEARANCE_REQUEST
where r.REQUEST_ID == 3
join cd in context.CLEARANCE_DOCUMENTS on r.CLEARANCE_TYPE equals cd.CLEARANCE_ID
join dt in context.DOCUMENT_TYPES on cd.DOCUMENT_ID equals dt.DOCUMENT_ID into outer
from t in outer.DefaultIfEmpty()
select new
{
r.REQUEST_ID,
cd.CLEARANCE_ID,
t.DOCUMENT_ID,
t.DOCUMENT_NAME,
is_set=(from b in context.CLEARANCE_REQUEST_DOCUMENT where
b.REQUEST_ID==r.REQUEST_ID && b.DOCUMENT_ID==t.DOCUMENT_ID
select new{b.IS_ORGINAL})
}
).ToList();
I want convert this Query to LINQ. Please help me. Thanks.
There is no need to manually join objects returned from an Entity Framework context.
See Why use LINQ Join on a simple one-many relationship?
If you use the framework as intended your job will be much easier.
var result = var clearanceTypes = context.CLEARANCE_REQUEST
.Single(r => r.REQUEST_ID == 3)
.CLEARANCE_DOCUMENTS
.SelectMany(dt => dt.DOCUMENT_TYPES)
.Select(a => new
{
DocumentType = a,
IsOriginal = a.CLEARANCE_REQUEST_DOCUMENT.is_original
});
Since your query won't be executed untill you iterate over the data, you can split your query in several subqueries to help you obtain the results like this:
var clearanceIds = context.CLEARANCE_REQUEST
.Where(r => r.REQUEST_ID == 3)
.Select(r => r.CLEARANCE_TYPE);
var documentIds = context.CLEARANCE_DOCUMENTS
.Where(dt => clearanceIds.Contains(dt.CLEARANCE_ID))
.Select(dt => dt.DOCUMENT_ID);
var result = context.DOCUMENT_TYPES
.Where(a => documentIds.Contains(a.DOCUMENT_ID))
.Select(a => new
{
// Populate properties here
IsOriginal = context.CLEARANCE_REQUEST_DOCUMENT
.Single(item => item.DOCUMENT_ID == a.DOCUMENT_ID &&
item.REQUEST_ID == 3)
.IS_ORIGINAL
})
.ToList();

How I can show all records with Linq To SQL?

I have 2 tables to join in a query as follows:
var query = (from c in Amenites_TBLs
join p in AmenitesContact_TBLs on c.AmenitesCodeID
equals p.AmenitesCodeID
// group c by p.AmenitesCodeID
into g
from cc in g.DefaultIfEmpty()
select new
{
AmenitiesCode = Amenites_TBLs.SingleOrDefault(a => a.AmenitesCodeID == cc.AmenitesCodeID).AmenitesCode,
CountryCode = Amenites_TBLs.SingleOrDefault(a => a.AmenitesCodeID == cc.AmenitesCodeID).CountryCode,
Director = AmenitesContact_TBLs.Where(a => a.TypeOfContact.StartsWith("Dir")).FirstOrDefault(a => a.AmenitesCodeID == cc.AmenitesCodeID).ContactName});
In the Table AmenitesContact_TBLs there are just 3 records. In the table Amenites_TBLs there are 300 records but the result of the query gives only 3 records and the other 297 rows are null but the fields AmenitiesCode and CountryCode are not null in the database (they get a value).
How can I modify my query to show all 300 records?
Try this:
Amenites_TBLs.Join(AmenitesContact_TBLs , c => c.AmenitesCodeID , p => p.AmenitesCodeID,(p,o) =>
new{ AmenitiesCode = c.AmenitesCode,CountryCode = c.CountryCode,Director = p.Where(a => a.TypeOfContact.StartsWith("Dir")).ContactName });

LINQ to SQL: GroupBy() and Max() to get the object with latest date

Consider a SQL Server table that's used to store events for auditing.
The need is to get only that latest entry for each CustID. We want to get the entire object/row. I am assuming that a GroupBy() will be needed in the query. Here's the query so far:
var custsLastAccess = db.CustAccesses
.Where(c.AccessReason.Length>0)
.GroupBy(c => c.CustID)
// .Select()
.ToList();
// (?) where to put the c.Max(cu=>cu.AccessDate)
Question:
How can I create the query to select the latest(the maximum AccessDate) record/object for each CustID?
I'm wondering if something like:
var custsLastAccess = db.CustAccesses
.Where(c.AccessReason.Length>0)
.GroupBy(c => c.CustID)
.Select(grp => new {
grp.Key,
LastAccess = grp
.OrderByDescending(x => x.AccessDate)
.Select(x => x.AccessDate)
.FirstOrDefault()
}).ToList();
you could also try OrderBy() and Last()
Using LINQ syntax, which I think looks cleaner:
var custsLastAccess = from c in db.CustAccesses
group c by c.CustID into grp
select grp.OrderByDescending(c => c.AccessDate).FirstOrDefault();
Here: this uses max rather than OrderByDesc, so should be more efficient.
var subquery = from c in CustAccesses
group c by c.CustID into g
select new
{
CustID = g.Key,
AccessDate = g.Max(a => a.AccessDate)
};
var query = from c in CustAccesses
join s in subquery
on c.CustID equals s.CustID
where c.AccessDate == s.AccessDate
&& !string.IsNullOrEmpty(c.AccessReason)
select c;

Categories

Resources