I have the following records:
name score Date
Billy 32470 12/18/2010 7:26:35 PM
Sally 1100 12/19/2010 12:00:00 AM
Kitty 1111 12/21/2010 12:00:00 AM
Sally 330 12/21/2010 8:23:34 PM
Daisy 32460 12/22/2010 3:10:09 PM
Sally 32460 12/23/2010 4:51:11 PM
Kitty 32440 12/24/2010 12:00:27 PM
Billy 32460 12/24/2010 12:11:36 PM
I want to get the leaderboard of the highest score with earliest time stamp using LINQ.
In this case, the correct one is
rank name
1 Billy
2 Daisy
3 Sally
I use the following query:
var result =
(from s in Submissions
group s by s.name into g
orderby g.Max(q => q.Score) descending,g.Min(q => q.Date) ascending
select new ScoreRecord
{
name = g.Key
Score = g.Max(q => q.Score)
}).Take(3).ToList();
I get the following wrong result:
rank name
1 Billy
2 Sally
3 Daisy
What's the correct linq query in this case?
At the moment you're getting the max score and the min date for a person but not necessarily the same record.
You need to restrict the min date to only look at those records that have the required max score... this isn't the cleanest way to do it but will work (I'm not good at Linq syntax, much prefer lambda)
var result =
(from s in Submissions
group s by s.name into g
orderby g.Max(q => q.Score) descending,
g.Where(i => i.Score == g.Max(q => q.Score)).Min(q => q.Date) ascending
select new ScoreRecord
{
name = g.Key
Score = g.Max(q => q.Score)
}).Take(3).ToList();
try something simple perhaps
var max = Submissions.Max(m => m.score);
var result = Submissions.Where(s => s.score == max).OrderBy(s => s.Date);
Related
I am hoping you can help.
I currently have a data structure like so I got after group by (on name year and state) linq aggregation query (this can not be changed)
Name Year State Total
Bobby 2015 East 5
Bobby 2015 West 5
Bobby 2015 North 10
Paul 2015 East 15
How can I transform above structure using linq to below structure.
Name Year East West North Total
Bobby 2015 5 5 10 20
Paul 2015 15 0 0 15
Keeping in mind I am trying to avoid using If statements like state=East ? Add east value : 0 in my linq groupby to get desired structure.
Thanks for help in advance.
Here's one way to do a pivot in Linq:
var pivot = data
.GroupBy(d => new {d.Name, d.Year})
.Select(g => new {
Name = g.Key.Name,
Year = g.Key.Year,
East = g.Where(c => c.State == "East").Sum(c => c.Total),
West = g.Where(c => c.State == "West").Sum(c => c.Total),
North = g.Where(c => c.State == "North").Sum(c => c.Total),
South = g.Where(c => c.State == "South").Sum(c => c.Total),
Total = g.Sum(c => c.Total),
});
You can do more dynamic pivots using DataTables (so you can add columns dynamically) but if your columns are known at design-time this method is cleaner IMHO.
i have two tables
1) Logs
2) Jobs
structure of both are as follows
Logs :- id, Emailid, LogDate
sampledata:- 1, a#a.com, jan24 1999
2, b#a.com, jan25 1999
3, a#a.com, jan25 1999
4, c#a.com jan26,1999
5, a#a.com jan27,1999
Jobs :- jid, job_name, job_viewed_by
sampledata:- j01, painter, a#a.com
j02, teacher, a#a.com
j01, painter, b#a.com
job_viewed_by is foreign key in jobs table and is related with Emailid in Logs table.
now i want a linq to entitites query which can give me
all Emailids from the logs tables who haved logged recently along with the no of jobs viewed (count of jobs) by them.
so as per above sample data my requirement is
a#a.com last logged on 27th jan.1999 and had viewed 2 jobs so far
b#a.com last logged on 24th jan.1999 had viewed 1 jobs so far
c#a.com last logged on 26th jan.1999. no jobs viewed
i know how to write it in SQL but i need to convert it using LinqtoEntities.
i tried a query but it give me number of recent logins rather than job counts.
var q= (from p in context.Logs
from x in context.ViewedJobs.Where(v=>p.EmailId ==v.ViewedBy)
group p by p.EmailId into grp
select new{ EmailId = grp.Key,
LastDate = grp.Max(g => g.LogDate),
Count=grp.Count() }).OrderByDescending(m=>m.LogDate);
Just smiple to try:
var q = from p in context.Logs
group p by p.Emailid into g
select new
{
EmailId=g.Key,
LastDate= g.Max(x => x.LogDate),
Count=context.ViewedJobs.Count(v=>v.ViewedBy==g.Key)
};
Update Version:
var q = from p in context.Logs
group p by p.Emailid into g
join j in context.ViewedJobs
on g.Key equlas j.ViewedBy into leftGroup
select new
{
EmailId=g.Key,
LastDate= g.Max(x => x.LogDate),
Count=leftGroup.Any()?leftGroup.Count():0
};
I need return just 2 lines in my query. One line with a string Today and a number of cases closed today, on my second line I need a string Last Week and a number of cases closed on the last week.
How I group with a range date?
Sum Name
----------- ----------
12 Today
33 Last Weeb
How about this:
var caseCounts = Cases
.Where(c => c.Date == today || (c.Date >= startOfLastWeek && c.Date <= endOfLastWeek))
.GroupBy(c => c.Date == today ? "Today" : "Last Week")
.Select(g => new {
Name = g.Key, Sum = g.Count()
});
You would need to define the 3 dates (today, startOfLastWeek, endOfLastWeek) before hand, but it gives you the results you are after.
GROUP BY YEARWEEK(date) should work. Depending on your dbms, you might be able to use another function, or program your own.
http://www.tutorialspoint.com/sql/sql-date-functions.htm#function_yearweek
I have a list of objects. E.g. List<coin> where they contain a string(denom) and int(year).
If the list contains:
"Quarter", 1954
"Quarter", 1990
"Penny", 1925
"Nickel", 1900
"Nickel", 2000
How can I get a resultant list where it contains the unique values with just the most recent year? E.g.:
"Quarter", 1990
"Penny", 1925
"Nickel", 2000
You can do this by grouping by name, then either ordering and taking the first result, or by using something like MaxBy from MoreLINQ:
var query = coins.GroupBy(x => x.Name)
.Select(g => g.MaxBy(x => x.Year));
or
var query = coins.GroupBy(x => x.Name)
.Select(g => g.OrderByDescending(x => x.Year).First());
You can do this using group by like:
var query = from coin in myList
group coin by coin.Name into grouped
select new
{
Name = grouped.Key
Year = grouped.Max(x => x.Year)
};
For another sample like this, check out "max - grouped" in the 101 Linq examples: http://msdn.microsoft.com/en-us/vcsharp/aa336747#maxGrouped
var coins = new Coin[] { ... };
var recentCoins =
from coin in coins
group coin by coin.Denom into g
select new
{
Denom = g.Key,
MostRecentYear = g.Max(c => c.Year)
};
I have a list like this:
List people
age name
1 bob
1 sam
7 fred
7 tom
8 sally
I need to do a linq query on people and get an int of the number distinct ages (3)
int distinctAges = people.SomeLinq();
how?
how?
Select out the age, then use Distinct and Count.
var ages = people.Select( p => p.Age ).Distinct().Count()
Or you could use GroupBy and Count
var ages = people.GroupBy( p => p.Age ).Count();
Download LinqPad and give these simple linq / lambda queries yourself. Its very easy to compare the SQL and equivalent Linq / lambda result set.
You would start with
select Age, Name
from People
group by Age, Name
Then open another tab
var ages = (from p in Peoples
group p by p.Age into g
select g);
ages.Dump();
Then open another tab
var ages = Peoples.GroupBy(p => p.Age);
ages.Dump();