LINQ group by on a single column - c#

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()
}

Related

SQL get Distinct rows from joined tables

I'm trying to determine the following from the joining of two tables:
Sample TableA: Contains 1 column consisting of unique IDs
ID Name Department
1 John IT
2 Jason Sales
3 Dany IT
4 Mike HR
5 Alex HR
Sample TableB: Contains multiple columns, including ID from TableA. For example:
ID AccountNumber WebID
1 10725 ABC1
1 10726 ABC1
1 10727 ABC1
2 20100 ABC2
2 20101 ABC2
3 30100 ABC3
4 40100 NULL
I want to get the following results:
ID Name WebID
1 John ABC1
2 Jason ABC2
3 Dany ABC3
4 Mike NULL
5 Alex NULL
I tried the following query, which is returning the correct rows for these sample tables:
Select count(a.ID), a.ID, a.Name, b.WebID from TableA a
left join TableB b on a.ID = b.ID
group by a.ID, a.Name, b.WebID
But my Actual Database tables, this query does not return correct number of rows: (30992)
TableA contains 29066 rows and TableB contains 23033 rows
The query should return 29066 rows, as it is Left Join.
When I checked the IDs that are in TableA, but not in TableB, there were 6033 rows:
Select * from TableA where ID not in (Select ID from TableB)
Am I missing something in the query?
TABLE B has duplicates of the ID column... the code below should work (but might not be the results you expect since I just do a max on the webid column which is fine if it is always the same but I need a rule if not)
I just saw you had a count... I added that in.
SELECT A.ID, A.Name, B.WebID
FROM TABLEA A
LEFT JOIN (
SELECT ID, MAX(WebID) AS WebID, count(*) as CNT
FROM TABLEB
GROUP BY ID
) B ON A.ID = B.ID
I think your query is as simple as that:
select a.ID,a.Name,b.WebID
from TableA a
left join TableB b on a.ID = b.ID

linq for records not having a value

I have table with values
Table Event
Id UserId EventId
===========================
1 1 1
2 1 2
3 1 3
4 2 2
Table Users
Id FirstName LastName
===========================
1 xx xx-last
2 ww ww-last
3 dd dd-last
4 qq qq-last
I want to have the list of users which forexample don't have EventId=1. in this case it would be
User 2,3,4
how can i make it with linq
Assuming that your User entity has an Events navigation property:
var usersWithoutEvent1 = dbContext.Users
.Where(u => u.Events.All(e => e.Id != 1))
.ToArrayAsync();

c# Linq How to write Innter Join using if condition

Here I have Two Tables Like
Employee
Id IsAccepected(bool) AccepectedBy EmpId
1 0 0 E1-1
2 1 2 E1-2
3 1 1 C1-1
Login
Id name
1 John
2 Mick
3 smith
Here my Question if IsAccepected==True then I need to Fetch Accepted By Record from Login Table
var x=(from n i in _db.EMployee
WHERE n.Empid='E1-1'
select n).Tolist();
foreach(var item in x){
if(item.IsAccepected==True){
.......
}
But I don't Need all those is it Possible to Write this condition Within The Linq
i guess you need this sql query need to be in linq right?
select b1.*,isnull((select 1 from A as a1 where a1.AccepectedBy=b1.Id and a1.EmpId='E1-2'),0) as isaccepted from B as b1
Something like below should work:
var x = from e in _db.Employee join l in _db.Login on e.AcceptedBy equals l.ID where e.Accepted == true select l;
Use this code by left join method-
select Login.name,Employee.EmpId from Employee left join Login on Employee.AccepectedBy=Login.Id where Employee.[IsAccepected(bool)]=1

Sort IQueryable by specific order

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);

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