Retrieve records who one field is max - linq

I have some records
id title date
1 aaa 2005
2 bbb 2003
3 aaa 2007
4 ccc 2005
5 ccc 2009
I need to query to retrieve records by Date is max
id title date
2 bbb 2003
3 aaa 2007
5 ccc 2009
Query:
select *
from Table
where Table.date = (SELECT Max(date)
FROM Table temp
WHERE temp.title = Document.title)
I have sql query but need Linq query for this action

Something like this should work (C#):
var results =
from x in db.table
group x by x.title into g
select g.OrderByDescending(x => x.date)
.First();
Now for proper paging you'd have to call Skip / Take on the entire query like this:
var results =
(from x in db.table
group x by x.title into g
select g.OrderByDescending(x => x.date)
.First())
.Skip(0)
.Take(10);

GroupBy title, order group enumeration by date descending, select first item. something like this:
db.EntityName.GroupBy( en => en.title ).Select( g => g.OrderByDescending( en => en.date ).First() )

Related

Need to get max date value from another table to order by product list

I have two tables.
First table is product table as below:
Product
Id Name
1 Apple
2 Desktop
3 Laptop
ProductStatus
Id ProductId LatestUpdatedDate
1 2 01-01-2021
2 2 08-07-2021
I am expecting the below result:
2 Desktop
1 Apple
3 laptop
How to make this query into linq?
Sample that i try
var query= _ProductRepository.Table;
var productStatusHistory = (from psh in _productStatusHistoryRepository.Table
group psh by psh.ProductId into g
select g.OrderByDescending(t => t.CreatedOnUtc).FirstOrDefault());
query = (from q in query
join ps in productStatusHistory on q.Id equals ps.ProductId into l_ps
from ps in l_ps.DefaultIfEmpty()
let index = ps == null ? default(DateTime) : ps.CreatedOnUtc
orderby index
select q);
This query working fine. I want to make this as single query

How to use LINQ Group By with Count

I want to convert the following SQL Query into Entity Framework + LINQ query. There are three tables Brands, Products and ProductReviews. Products table has BrandId as FK and ProductReviews has ProductId as FK.
SELECT Top 5 b.Id, b.ShortName, COUNT(r.Id) AS TotalReviews
FROM ProductsReviews r
INNER JOIN Products p ON r.ProductId = p.Id
INNER JOIN Brands b ON p.BrandId = b.Id
GROUP BY b.Id, b.ShortName
Order By TotalReviews desc
Basically, I want to display top 5 brands based on the reviews posted for the products of those brands. I want output like below:
Id ShortName TotalReviews
-----------------------------------------
76 Adidas 61
120 Yamaha 29
109 Tommy Hilfiger 26
61 Mothercare 25
31 Haier 22
pseudocode
var results =
( from r in ProductsReviews
join p in Products on r.ProductId equals p.Id
join b in Brands on p.BrandId equals b.Id
group c by new {
b.Id,
b.ShortName } into grp
select new {
Id = grp.key.Id,
ShortName = grp.key.ShortName,
TotalReviews = grp.Count()}
)
.OrderBy(x=>x.TotalReviews).Take(5);
It really depends on how your model is setup with EF.
If you have added relations in your model, the query could be as simple as
var result = context.ProductReviews.OrderByDescending(x => x.TotalReviews).Select(x => new { x.BrandId, X.Brand.ShortName, x.TotalReviews});
Because you are not selecting anything from Product, I am not including it in the query. If you have relationships in your EF, we would be able to use navigation properties such as x.Brand.Someproperty, and EF will handle creating the query based upon the model that you have setup.
the result variable will contain the query and once you access the values, the query will be executed. Lastly to only select the top 5 you would simply use the Take function like so
var result = context.ProductReviews.OrderByDescending(x => x.TotalReviews).Select(x => new { x.BrandId, X.Brand.ShortName, x.TotalReviews}).Take(5);
Regards
Louis

retrieving using linq query and entityframework

I have table structure like below
Employee Table
ID Name
1 A
2 B
3 C
4 D
5 E
Employee allocation table
Alocationid ID Date
1 2 26/6/2013
2 2 25/6/2013
3 1 25/6/2013
4 1 24/6/2013
5 3 24/6/2013
6 4 26/6/2013
Now i need to get the available employees for a particular date.for example if i need available employees for 25/6/2013 then the result would be like below:-
ID Name
1 A
3 C
4 D
101 Linq is a good reference site and this sample seems most appropriate to your situation.
If you are working with repositories and want a less query like approach you could use the following:
IQueryable<int> allocatedEmployeeIds = AllocationRepository.DbSet.Where(x => x.Date == referenceDate).Select(x => x.ID);
List<Employee> allocatedEmployees = EmployeeRepository.DbSet.Where(x => allocatedEmployeeIds.Any(y => y == x.ID).ToList();
Edit: and if you want those not allocated it is just a matter of adding "!"
IQueryable<int> allocatedEmployeeIds = AllocationRepository.DbSet.Where(x => x.Date == referenceDate).Select(x => x.ID);
List<Employee> allocatedEmployees = EmployeeRepository.DbSet.Where(x => !allocatedEmployeeIds.Any(y => y == x.ID).ToList();
Use group joing to get allocations of each employee. Then select those employees, which don't have any allocations for particular date:
from e in db.Employees
join ea in db.EmployeeAllocations
on e.ID equals ea.ID into g
where !g.Any(x => x.Date == date)
select e

LINQ distinct on 2 fields

I have a LINQ query that returns data and I want to filter based on 2 fields (fkProfileID and fkOrgID) that are often the same. I only want to show 1 record when fkProfileID and fkOrgID match, so it is similar to doing an SQL distinct, but on 2 fields rather than one.
My data will look like this (other fields have been removed) :
fkProfileID fkOrgID
1 1001
1 1001
1 1001
2 1001
2 1001
1 1005
1 1005
So here I want to return only the following:
fkProfileID fkOrgID
1 1001
2 1001
1 1005
Here is my current LINQ (both fields above are in tblUserRights), how do I need to change it to do this?
List<ProfileJSON> lstProfiles = (from r in _database.tblUserRights
join p in _database.LuProfiles on r.fkProfileID equals p.luProfileID
join o in _database.tblOrganisations on r.fkOrgID equals o.pkOrgID
where r.fkUniqueID == intPKUserID
orderby o.OrgDesc, p.ProfileName
select new ProfileJSON
{
SiteID = o.pkOrgID,
SiteName = o.OrgDesc,
ProfileID = p.luProfileID,
ProfileName = p.ProfileName
}).ToList();
You can use .Distinct() after your query
List<ProfileJSON> lstProfiles = (from r in _database.tblUserRights
join p in _database.LuProfiles on r.fkProfileID equals p.luProfileID
join o in _database.tblOrganisations on r.fkOrgID equals o.pkOrgID
where r.fkUniqueID == intPKUserID
orderby o.OrgDesc, p.ProfileName
select new ProfileJSON
{
SiteID = o.pkOrgID,
SiteName = o.OrgDesc,
ProfileID = p.luProfileID,
ProfileName = p.ProfileName
}).Distinct().ToList(); //Distinct here

How to get the last element by date of each "type" in LINQ or TSQL

Imagine to have a table defined as
CREATE TABLE [dbo].[Price](
[ID] [int] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Price] [int] NOT NULL
)
where ID is the identifier of an action having a certain Price. This price can be updated if necessary by adding a new line with the same ID, different Price, and a more recent date.
So with a set of a data like
ID StartDate Price
1 01/01/2009 10
1 01/01/2010 20
2 01/01/2009 10
2 01/01/2010 20
How to obtain a set like the following?
1 01/01/2010 20
2 01/01/2010 20
In SQL, there are several ways to say it. Here's one that uses a subquery:
SELECT *
FROM Price p
WHERE NOT EXISTS (
SELECT *
FROM Price
WHERE ID = p.ID
AND StartDate > p.StartDate
)
This translates fairly trivially to LINQ:
var q = from p in ctx.Price
where !(from pp in ctx.Price
where pp.ID == p.ID
&& pp.StartDate > p.StartDate
select pp
).Any()
select p;
Or should I say, I think it does. I'm not in front VS right now, so I can't verify that this is correct, or that LINQ will be able to convert it to SQL.
Minor quibble: Don't use the name ID to store a non-unique value (the type, in this case). It's confusing.
Assuming ID & StartDate will be unique:
SELECT p.ID, p.StartDate, p.Price
FROM Price p
JOIN
(
SELECT ID, MAX(StartDate) AS LatestDate
FROM Price
GROUP BY ID
) p2 ON p.ID = p2.ID AND p.StartDate = p2.LatestDate
Since you tagged your question with LINQ to SQL, here is an LINQ query to express what you want:
from price in db.Prices
group price by price.Id into group
let maxDateInGroup = group.Max(g => g.StartDate)
let maxDatePrice = group.First(g => g.StartDate == maxDateInGroup)
select
{
Id = group.Key,
StartDate = maxDatePrice.StartDate,
Price = maxDatePrice.Price
};

Resources