Hi i develop web app with c#. I have sql query and i convert to linq but it's not working true because of order by
My sql query
Select TOP 3 HastalikIsmi From Hastaliklar group by HastalikIsmi order by Count(*) desc
My linq
public List<HastalikDto> GetHastalikDto()
{
using (SirketDBContext context = new SirketDBContext())
{
var result = from hastalik in context.Hastaliklar
group hastalik by hastalik.HastalikIsmi into isim
select new HastalikDto { HastalikIsmi = isim.Key };
return result.OrderBy(h => h.HastalikIsmi).Take(3).ToList();
}
}
Here's how you can do the order by on the count of each group and take the 3 with the highest count.
var result = context.Hastaliklar
.GroupBy(x => x.HastalikIsmi)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(3)
.ToList();
Related
What I am trying to do is get the top 10 most sold Vegetables by grouping them by an Id passed by parameter in a function and ordering them by the sum of their Quantity. I don't know how to use SUM or (total) quite yet but I thought I'd post it here seeking help. If you need me offering you anything else I will be ready.
This is my code:
TheVegLinQDataContext db = new TheVegLinQDataContext();
var query =db.OrderDetails.GroupBy(p => p.VegID)
.Select(g => g.OrderByDescending(p => p.Quantity)
.FirstOrDefault()).Take(10);
And this is an image of my database diagram
Group orders by Vegetable ID, then from each group select data you want and total quantity:
var query = db.OrderDetails
.GroupBy(od => od.VegID)
.Select(g => new {
VegID = g.Key,
Vegetable = g.First().Vegetable, // if you have navigation property
Total = g.Sum(od => od.Quantity)
})
.OrderByDescending(x => x.Total)
.Select(x => x.Vegetable) // remove if you want totals
.Take(10);
Since this is not clear that you are passing what type of id as function parameter, I'm assuming you are passing orderId as parameter.
First apply where conditions then group the result set after that order by Total sold Quantity then apply Take
LINQ query
var result = (from a in orderdetails
where a.OrderId == orderId //apply where condition as per your needs
group a by new { a.VegId } into group1
select new
{
group1.Key.VegId,
TotalQuantity = group1.Sum(x => x.Quantity),
group1.FirstOrDefault().Vegitable
}).OrderByDescending(a => a.TotalQuantity).Take(10);
Lamda (Method) Syntax
var result1 = orderdetails
//.Where(a => a.OrderId == 1) or just remove where if you don't need to filter
.GroupBy(x => x.VegId)
.Select(x => new
{
VegId = x.Key,
x.FirstOrDefault().Vegitable,
TotalQuantity = x.Sum(a => a.Quantity)
}).OrderByDescending(x => x.TotalQuantity).Take(10);
How would you write a linq query with the following SQL statement. I've tried several methods referenced on stackoverflow but they either don't work with the EF version I'm using (EF core 3.5.1) or the DBMS (SQL Server).
select a.ProductID, a.DateTimeStamp, a.LastPrice
from Products a
where a.DateTimeStamp = (select max(DateTimeStamp) from Products where a.ProductID = ProductID)
For reference, a couple that I've tried (both get run-time errors).
var results = _context.Products
.GroupBy(s => s.ProductID)
.Select(s => s.OrderByDescending(x => x.DateTimeStamp).FirstOrDefault());
var results = _context.Products
.GroupBy(x => new { x.ProductID, x.DateTimeStamp })
.SelectMany(y => y.OrderByDescending(z => z.DateTimeStamp).Take(1))
Thanks!
I understand you would like to have a list of the latest prices of each products?
First of all I prefer to use group by option even over 1st query
select a.ProductID, a.DateTimeStamp, a.LastPrice
from Products a
where a.DateTimeStamp IN (select max(DateTimeStamp) from Products group by ProductID)
Later Linq:
var maxDateTimeStamps = _context.Products
.GroupBy(s => s.ProductID)
.Select(s => s.Max(x => x.DateTimeStamp)).ToArray();
var results = _context.Products.Where(s=>maxDateTimeStamps.Contains(s.DateTimeStamp));
-- all assuming that max datetime stamps are unique
I've managed to do it with the following which replicates the correlated sub query in the original post (other than using TOP and order by instead of the Max aggregate), though I feel like there must be a more elegant way to do this.
var results = from x
in _context.Products
where x.DateTimeStamp == (from y
in _context.Products
where y.ProductID == x.ProductID
orderby y.DateTimeStamp descending
select y.DateTimeStamp
).FirstOrDefault()
select x;
I prefer to break up these queries into IQueryable parts, do you can debug each "step".
Something like this:
IQueryable<ProductOrmEntity> pocoPerParentMaxUpdateDates =
entityDbContext.Products
//.Where(itm => itm.x == 1)/*if you need where */
.GroupBy(i => i.ProductID)
.Select(g => new ProductOrmEntity
{
ProductID = g.Key,
DateTimeStamp = g.Max(row => row.DateTimeStamp)
});
//// next line for debugging..do not leave in for production code
var temppocoPerParentMaxUpdateDates = pocoPerParentMaxUpdateDates.ToListAsync(CancellationToken.None);
IQueryable<ProductOrmEntity> filteredChildren =
from itm
in entityDbContext.Products
join pocoMaxUpdateDatePerParent in pocoPerParentMaxUpdateDates
on new { a = itm.DateTimeStamp, b = itm.ProductID }
equals
new { a = pocoMaxUpdateDatePerParent.DateTimeStamp, b = pocoMaxUpdateDatePerParent.ProductID }
// where
;
IEnumerable<ProductOrmEntity> hereIsWhatIWantItems = filteredChildren.ToListAsync(CancellationToken.None);
That last step, I am putting in an anonymous object. You can put the data in a "new ProductOrmEntity() { ProductID = pocoMaxUpdateDatePerParent.ProductID }...or you can get the FULL ProductOrmEntity object. Your original code, I don't know if getting all columns of the Product object is what you want, or only some of the columns of the object.
SELECT
[TimeStampDate]
,[User]
,count(*) as [Usage]
FROM [EFDP_Dev].[Admin].[AuditLog]
WHERE [target] = '995fc819-954a-49af-b056-387e11a8875d'
GROUP BY [Target], [User] ,[TimeStampDate]
ORDER BY [Target]
My database table has the columns User, TimeStampDate, and Target (which is a GUID).
I want to retrieve all items for each date for each user and display count of entries.
The above SQL query works. How can I convert it into LINQ to SQL? Am using EF 6.1 and my entity class in C# has all the above columns.
Create Filter basically returns an IQueryable of the entire AuditLogSet :
using (var filter = auditLogRepository.CreateFilter())
{
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => i.Target, i => i.User, i => i.TimeStamp);
audits = query.ToList();
}
Am not being allowed to group by on 3 columns in LINQ and I am also not sure how to select like the above SQL query with count. Fairly new to LINQ.
You need to specify the group by columns in an anonymous type like this:-
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(x => new { x.User, x.TimeStampDate })
.Select(x => new
{
TimeStampDate= x.Key.TimeStampDate,
User = x.Key.User,
Usage = x.Count()
}).ToList();
Many people find query syntax simpler and easier to read (this might not be the case, I don't know), here's the query syntax version anyway.
var res=(from it in filter.All
where it.Target=="995fc819-954a-49af-b056-387e11a8875d"
group it by new {it.Target, it.User, it.TimeStampDate} into g
orderby g.Key.Target
select new
{
TimeStampDate= g.Key.TimeStampDate,
User=g.Key.User,
Usage=g.Count()
});
EDIT: By the way you don't need to group by Target neither OrderBy, since is already filtered, I'm leaving the exact translation of the query though.
To use GroupBy you need to create an anonymous object like this:
filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => new { i.Target, i.User, i.TimeStamp });
It is unnecessary to group by target in your original SQL.
filter.All.Where( d => d.Target == "995fc819-954a-49af-b056-387e11a8875d")
.GroupBy(d => new {d.User ,d.TimeStampDate} )
.Select(d => new {
User = d.Key.User,
TimeStampDate = d.Key.TimeStampDate,
Usage = d.Count()
} );
I'm trying to convert query of queries used in ColdFusion to LINQ and C#. The data come from data files, rather than from the database.
I converted the first query, but have no clue as to
how to use it to query the second query.
how to include count(PDate) as DayCount in the second query.
Below is the code using query of queries in ColdFusion:
First query
<cfquery name="qSorted" dbtype = "query">
SELECT OA, CD,PDate,
FROM dataQuery
GROUP BY CD,OA,PDate,
</cfquery>
Second query
<cfquery name="qDayCount" dbtype = "query">
SELECT OA, CD, count(PDate) as DayCount
FROM qSorted // qSorted is from the first query.
GROUP BY
OA, CD
ORDER BY
OA, CD
</cfquery>
Here's the first converted LINQ query, and it works fine:
var Rows = allData.SelectMany(u => u._rows.Select(t => new
{
OA = t[4],
CD = t[5],
PDate = t[0]
}))
.GroupBy(x => new { x.CD, x.OA, x.PDate })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
g.Key.PDate
})
.ToList();
Here's the pseudo-code for the second LINQ query, which I need your assistance:
var RowsDayCount = Rows //Is this correct? If not, how to do it?
.GroupBy(x => new { x.OA, x.PDate, x.CD, })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
g.Key.PDate,//PDate should be PDate.Distinct().Count() asDayCount
// See DayCount in cfquery name="qDayCount" above.
})
.OrderBy(u => u.OA)
.ThenBy(u => u.CD)
.ToList();
Your second query origionally wasn't grouping on PDate, but your translation is. That's wrong. If you want to count the number of PDates for each OA/CD pair, you need to not group on PDate. Once you've made that change, you can modify the Select to pull out all of the PDate values from the group, and count the distinct values.
.GroupBy(x => new { x.OA, x.CD, })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
DayCount = g.Select(item => item.PDate).Distinct().Count(),
})
I'm trying to convert this T-SQL to a LINQ-SQL query:
-- top 3 pros for city
select top 3 description, ispro, COUNT(*) as numberofvotes
from tblProCon
where IdPrimaryCity = #IdPrimaryCity
and IsPro = 1
group by IdPrimaryCity, IsPro, description
union
-- top 3 cons for city
select top 3 description, ispro, COUNT(*) as numberofvotes
from tblProCon
where IdPrimaryCity = #IdPrimaryCity
and IsPro = 0
group by IdPrimaryCity, IsPro, description
order by ispro, numberofvotes desc
Here's what i have so far:
// Construct base query
var query = (from p in db.tblProCons
where p.IdPrimaryCity == idPrimaryCity
group p by new { p.IdPrimaryCity, p.IsPro, p.Description } into g
select new { Description = g.Key, IsPro = g.Any(x => x.IsPro), NumberOfAgrees = g.Count() });
// Split queries based on pro/con, and apply TOP(3)
var pros = query.Where(x => x.IsPro).Take(3);
var cons = query.Where(x => !x.IsPro).Take(3);
result = pros
.Union(cons) // Union pro/cons
.OrderByDescending(x => x.IsPro) // Order #1 - Pro/Con
.ThenByDescending(x => x.NumberOfAgrees) // Order #2 - Number of Agree's
.Select(x => new ProCon // project into cut-down POCO
{
Description = x.Description,
IsPro = x.IsPro
}).ToList();
But she ain't working. :(
x.Description is complaining "Cannot convert source type {IdPrimaryCity:int, IsPro:bool, Description:string} to target type string".
All i want to end up with is a List<ProCon>, having the description (string), and flag indicating if it's a pro or con.
What am i doing wrong?
Nevermind, i got it, the "group" projection was all wrong.
Here's the working solution:
// Construct base query
var query = (from p in db.tblProCons
where p.IdPrimaryCity == idPrimaryCity
group p by new { p.IdPrimaryCity, p.IsPro, p.Description } into g
select new { ProCon = g.Key, NumberOfAgrees = g.Count() });
// Split queries based on pro/con, and apply TOP(3)
var pros = query.Where(x => x.ProCon.IsPro).Take(3);
var cons = query.Where(x => !x.ProCon.IsPro).Take(3);
result = pros
.Union(cons) // Union pro/cons
.OrderByDescending(x => x.ProCon.IsPro) // Order #1 - Pro/Con
.ThenByDescending(x => x.NumberOfAgrees) // Order #2 - Number of Agree's
.Select(x => new ProCon // project into cut-down POCO
{
Description = x.ProCon.Description,
IsPro = x.ProCon.IsPro
}).ToList();