Sort IQueryable by specific order - c#

I have a table that I want to pull items by name in a certain order and by date.
id name date
1 XYZ 1:30
2 ABC 1:40
3 LMNOQ 1:50
4 ABC 1:20
I created the order
List<string> itemNames = new List<string>();
documentOrder.Add("XYZ");
documentOrder.Add("ABC");
documentOrder.Add("LMNOQ");
Then pulled the data, I think order will stay intact.
var myTable = _context.TheTable.Where(x => itemNames.Contains(x.id));
myTable data will look like
id name date
1 XYZ 1:30
2 ABC 1:40
4 ABC 1:20
3 LMNOQ 1:50
Now I need to sort by dates without messing up the name order. I need it look like this.
id name date
1 XYZ 1:30
2 ABC 1:20
4 ABC 1:40
3 LMNOQ 1:50

var myTable = _context.TheTable.Where(x => itemNames.Contains(x.id))
.OrderBy(x => x.name).ThenBy(x => x.date);

When using an IQueryable you can get it ordered as you want (by name, then by date... which looks a bit like a time) with multiple ordering statements.
var orderedQueryable = queryable.OrderBy(q => q.Name).ThenBy(q => q.Date);

Related

Select and grouping based on different fields/integer

Table in SQL:
Document Revision Version
-----------------------------------------------------
ABC 1 1
ABC 1 2
ABC 1 8
ABC 2 3
DocumentF 1 3
DocumentF 1 2
Expected output:
Document Revision Version
-----------------------------------------------------
ABC 1 8
ABC 2 3
DocumentF 1 3
Basically if there are two versions of the same revision, bring back the latest based on version.
I've tried the following:
var list = from document in documents
group document by document.Document
into groups
from g in groups
group g by g.Revision
into final
select final.OrderByDescending(d => d.Version).FirstOrDefault();
The above code produces the following:
Document Revision Version
-----------------------------------------------------
ABC 2 3
DocumentF 1 3
Using Linq , we can group by multiple properties like below
var list = from document in documents
group document by (document.Document, document.Revision)
into groups
select groups.OrderByDescending(d => d.Version).FirstOrDefault();
You need to GroupBy multiple columns, something like this:
var result = documents.GroupBy(c => new { c.Document, c.Revision })
.Select(c => new DocumentClass
{
Document = c.Key.Document,
Revision = c.Key.Revision,
Version = c.Max(d=>d.Version)
}).ToList();

LINQ group by on a single column

I have a database table that looks like this:
ID USERID DATE NAME
1 1 01-01-2001 aaaa
1 2 01-02-2001 aaaa
1 3 01-03-2001 aaaa
2 5 02-02-2002 bbbb
2 6 02-02-2002 bbbb
2 7 02-02-2002 bbbb
So I want to group everything by ID, so it has multiple USERIDs for each ID. However DATE and NAME are all the same. So how do get this as a linq query?
So far I thought of doing this, and this works for the users
from table in context.table
group table.USERID by table.ID into grp
orderby grp.Key descending
select new
{
ID = grp.Key,
Users = grp.ToList()
}
But this does not work if I add other items like DATE because DATE is sometimes different. However if it would select the first date that would be just fine.
EDIT what I would like as result is:
ID Users DATE NAME
1 1,2,3 01-01-2001 aaaa
2 5,6,7 02-02-2002 bbbb
You group by multiple columns:
from table in context.table
group new{table.UserID,table.Date} by new{table.ID,table.Name} into grp
orderby grp.Key.ID descending
select new
{
ID = grp.Key.ID,
Date=grp.FirstOrDefault().Date,
Name=grp.Key.Name,
Users = grp.Select(e=>e.UserID).ToList()
}

How to get multiple records of different employee in same date using EF

I have a table where I store multiple records,of multiple employees,I want a query that return total records of all employee in one date just and ignore all other occurrence which may b in different dates.
id username date cnic. amount
1. AkA. 12_09_16. 1234. 2000
2. AkA same 1234. 20
3. Zzz. Same. 234. 5000
4. Zzz same. 234. 300
5. AkA. 13_09_16. 1234. 250
C# format,not sql
As I've understood correctly you can try to use the following code:
public IList<string> GetUserNames(DateTime specificDate)
{
var userNames = Entries.Where(x => x.Date == specificDate)
.Select(x => x.UserName)
.Distinct()
.ToList();
return userNames;
}

distinct values in a Linq to sql string.Join()

I have a table which contains the schedule for a class. it contains the teacherid and name, datetime of the class and the course for that specific time.
teacherid teachername startdate coursename
1 john 9/1/2014 10:00 math
2 john 9/2/2014 10:00 math
3 jane 9/3/2014 10:00 english
4 john 9/4/2014 10:00 french
5 jack 9/5/2014 10:00 history
6 jane 9/6/2014 10:00 math
I want to write a linq to sql query which returns which teacher gives which courses, as such:
Teachername courses
john math, french
jane english, math
jack history
I've gotten as far as the following
var _classes = from _c in dbContext.classes
where _c.StartDate < System.DateTime.Now
group _c by new
{
_c.TeacherId,
_c.TeacherName,
_c.CourseName
} into g
select new
{
g.Key.TeacherName,
courses = string.Join(",", from i in g select i.CourseName)
};
but i'm getting the following output
Teachername courses
john math, math, french
jane english, math
jack history
so john is getting the math value twice.
how do I make the string.Join function use distinct values?
thanks
There is no query syntax for distinct so you should change to method syntax:
courses = string.Join(",", g.Select(i => i.CourseName).Distinct())
Add Distinct to your select clause in String.Join like:
courses = string.Join(",", (from i in g select i.CourseName).Distinct())
Or use method Syntax for select as well like:
courses = string.Join(",", (g.Select(i=> i.CourseName).Distinct())

Get the first record of a group in LINQ? [duplicate]

This question already has answers here:
How to get first record in each group using Linq
(7 answers)
Closed 5 years ago.
Summary: How to get top 1 element in ordered groups of data
I am trying to group by a CarId field , and then within each group, I want to sort on a DateTimeStamp field descending. The desired data would be for each Car give me the latest DateTimeStamp and only that 1 in the group.
I can get to this point, but having problems taking the top 1 off of the group and ordering the group by DateTimeStamp desc.
Here is what I have after the first group operation:
group 1
------------------------
CarId DateTimeStamp
1 1/1/2010
1 1/3/2010
1 3/4/2010
group 2
------------------------
CarId DateTimeStamp
2 10/1/2009
2 1/3/2010
2 9/4/2010
what I would desire only the top 1 in an ordered group
group 1
------------------------
CarId DateTimeStamp
1 3/4/2010
group 2
------------------------
CarId DateTimeStamp
2 9/4/2010
Brickwall: Where I get stopped, is needing the CarId and DateTimeStamp in the group by clause, in order to later sort by the DateTimeStamp. Maybe the sorting of the date should be done in a separate function, not sure.
data
.GroupBy(
x => x.CardId,
(x, y) => new {
Key = x,
Value = y.OrderByDescending(z => z.DateTimeStamp).FirstOrDefault()
}
);
This will group all the elements by CardId, then order the elements of each group by DateTimeStamp (descending), then pare down each group to only contain the first element. Finally, it returns an enumerable of "groups" (with the scare quotes since they're actually an anonymous type instead of an IGrouping) where each group has the one item you're seeking.
I find the query expression syntax easier to understand myself:
from x in data
group x by x.CarId into grp
select new {
CarId = x.CarId,
Record = (from x in grp orderby z.DateTimeStamp descending).FirstOrDefault()
};

Categories