Linq query with group by clause - linq

My table has following columns:-
LevelId, LevelName, ScenarioId, TeamId.
I want to select LevelName corresponding to minimum LevelId when grouped by teamId

So, you want to:
Group by team ID
Within each group, order by level ID
Take the first result's level name
So that sounds like:
var query = table.GroupBy(x => x.TeamId)
.Select(g => g.OrderBy(x => x.LevelId).First().Name);
Don't just take this query and include it in your code though - make sure you understand it so you can come up with your own solution next time you have something similar to do.
If this is in LINQ to Objects, you may find that MoreLINQ would be useful, with its MinBy method:
var query = table.GroupBy(x => x.TeamId)
.Select(g => g.MinBy(x => x.LevelId).Name);
This avoids ordering the whole group, just to find the entry with the minimum level ID.

Related

NotSupportedException for LINQ Queries

I am trying to get a list of a database table called oracleTimeCards whose employee id equals to the employeeID in employees list. Here is what I wrote:
LandornetSQLEntities db = new LandornetSQLEntities();
List<OracleEmployee> employees = db.OracleEmployees.Where(e => e.Office.Contains(officeName) && e.IsActive == true).Distinct().ToList();
var oracleTimeCards = db.OracleTimecards.Where(c => employees.Any(e => c.PersonID == e.PersonID)).ToList();
Anyone has any idea?
I'm going to assume you're using Entity Framework here. You can't embed calls to arbitrary LINQ extension methods inside your predicate, since EF might not know how to translate these to SQL.
Assuming you want to find all the timecards for the employees you found in your first query, you have two options. The simplest is to have a navigation property on your Employee class, named let's say TimeCards, that points to a collection of time card records for the given employee. Here's how that would work:
var oracleTimeCards = employees
.SelectMany(e => e.TimeCards)
.ToList();
If you don't want to do this for whatever reason, you can create an array of employee IDs by evaluating your first query, and use this to filter the second:
var empIDs = employees
.Select(e => e.PersonID)
.ToArray();
var oracleTimeCards = db.OracleTimecards
.Where(tc => empIDs.Contains(tc.PersonID))
.ToList();

linq query with count

I would like to create a simple linq query, but I don't really know, how it should be. I have searched the net, but found nothing, what I can use or I don't know yet, that I could use it.
So, basically, I have a table with this fields: reference, vat_code, amount, vat_amount, supplier.
Now, I would like to query the records, where reference<>'' and the reference is more than once in the table. But I need all the occupians.
F.e. from
1;VF;100;27;345
2;VF;200;54;123
2;VF;-200;-54;123
2;VF;200;54;123
3;VF;300;81;888
to
2;VF;200;54;123
2;VF;-200,-54;123
2;VF;200;54;123
How would be look the linq query to this?
Thanks.
If rows with same reference should go together in results, then you should filter out rows with reference equal to empty string, then group all rows by reference and select only those groups which have more than one row.
C# sample with DataTable:
var result = dt.AsEnumerable()
.Where(r => r.Field<string>("reference") != "")
.GroupBy(r => r.Field<string>("reference"))
.Where(g => g.Count() > 1)
.SelectMany(g => g); // flatten group to sequence of rows

JoinQueryOver in QueryOver to select notin list

I have a list of record that I picked up through the code:
var list= NhSession.QueryOver<Data.Models.MembModel>()
.Where(w => w.Comp.Id == idcomp)
.JoinQueryOver(jq => jq.Ver)
.Select(s => s.Ver)
.List<Dados.Models.VerModel>();
With this code I get a list of VerModel that I have relation in a MembModel. The problem is that I what get the list of VerModel that don't be in relation in a MembModal, I think to describe this, I want to select one list that is "notin" a first list. How can I do this?
Tks
What we need, as you said, is a NOT IN (subquery) statement. And NHibernate does have a clear way how to achieve that. First the subquery, which will return MembModel collection (filtered or not - as needed), represented by the VerModel.ID
var subquery = QueryOver.Of<Data.Models.MembModel>()
// we can still filter this sub-select ... or not
// .Where(w => w.Comp.Id == idcomp)
// what we need to be returned is the reference id, the VerModel.ID
.Select(m => m.Ver.ID);
And now we will query the VerModel itself, with the NOT IN (subquery) clause:
var list = session.QueryOver<Dados.Models.VerModel>()
.WithSubquery
.WhereProperty(v => v.ID) // the ID to match the prev selected one
.NotIn(subquery) // should NOT be IN
.List<Dados.Models.VerModel>();
Check:
16.8. Subqueries

Linq and Lambda expression for a complex sql query involving joins

Using Linq to Entity (Entity Framework) in MVC 3 project.
My model:
Table - Users
UserID (PK)
...
Table - Clients
ClientID (PK)
Table - PropertyItems
PropertyItemID (PK)
Table - MemberContactPreference (Contains PropertyItems selected by Users- many to many)
UserID(FK)
PropertyItemID(FK)
Table ClientProperties (Contains PropertyItems that belong to Clients - many to many)
ClientID (FK)
PropertyItemID (FK)
I want to list all the distinct users that have selected all the properties selected by clients.
My Approach :
I got a list of all properties for a particular client in
Iqueryable<ClientProperty> clientProperties = GetClientProperties(ClientID)
Iqueryable<User> UsersMatchingClientProperties = GetAllUsers();
foreach (ClientProperty property in clientproperties)
{
UsersMatchingClientProperties = (from uem in UsersMatchingClientProperties
join ucp in GetAllMemberContactPreferences on
ucp.UserID == uem.UserID
where uem.MemberContactPreferences.SelectMany(
mcp => mcp.PropertyItemID == property.PropertyItemID)
select uem).Distinct;
}
It gives the right result only first time. As it doesn't reduce the number of items in UsersMatchingClientProperties with each iteration. actually it replaces the collection with new resultset. I want to filter out this collection with each iteration.
Also, any suggestions to do this in Lambda expression without using Linq.
Thanks
That generation of an iqueryable in a for loop seems like a dangerous thing, which could end up in a monster sql join being executed at once.
Anyway, I don't think you need that. How about something like this?
// for a given client, find all users
// that selected ALL properties this client also selected
Iqueryable<ClientProperty> clientProperties = GetClientProperties(ClientID)
Iqueryable<User> allUsers= GetAllUsers();
Iqueryable<MemberContactPreference> allMemberContactProperties = GetAllMemberContactPreferences();
Iqueryable<User> UsersMatchingClientProperties = allUsers
.Where(user => allMemberContactProperties
.Where(membP => membP.UserID==user.UserID)
.All(membP => clientProperties
.Select(clientP => clientP.PropertyID)
.Contains(membP.PropertyID)
)
);
Here is an alternative query in case you want the users that selected ANY property for a given client
// for a given client, find all users
// that selected ANY properties this client also selected
Iqueryable<ClientProperty> clientProperties = GetClientProperties(ClientID)
Iqueryable<User> allUsers= GetAllUsers();
Iqueryable<MemberContactPreference> allMemberContactProperties = GetAllMemberContactPreferences();
Iqueryable<User> UsersMatchingClientProperties = clientproperties
.Join(allMembersContactProperties, // join clientproperties with memberproperties
clientP => clientP.PropertyItemID,
membP => membP.PropertyItemID,
(clientP, membP) => membP)) // after the join, ignore the clientproperties, keeping only memberproperties
.Distinct() // distinct is optional here. but perhaps faster with it?
.Join(allUsers, //join memberproperties with users
membP => membP.UserID,
user => user.UserID,
(membP, user) => user)) // after the join, ignore the member properties, keeping only users
.Distinct();
I trust Hugo did a good job suggesting ways to improve your query (+1). But that does not yet explain the cause of your problem, which is the modified closure pitfall.
I think that after your loop there is some code that actually executes the query in UsersMatchingClientProperties. At that moment the query is executed with the last value of the loop variable property! (The loop variable is the closure in each query delegate that is created in an iteration, and it is modified by each iteration).
Change the loop like this:
foreach (ClientProperty property in clientproperties)
{
var property1 = property;
...
and use property1 in the query. That should solve the cause of the problem. But as said, it looks like the whole process can be improved.

How do I order a Group by and Order by a result using Linq

I have datetime values (e.g. 12/01/2010 10:10:222..) How can I display just the year in desc order? For example, 2011, 2010, 2009, 2008, etc.. I need to group by just the year part of the field and return that. I actually need to return the year and the name. I need to use the name for other functionality, which is why I need the 2 values.
Thanks for any help...
It's not really clear what you mean, but you might just want something like:
var query = collection.GroupBy(record => record.DateProperty.Year)
.OrderBy(group => group.Key);
If that's not what you're after, please provide more details - ideally some sample input and desired output.
If you only want one entry from each group and you're happy to take any arbitrary one to get the name, and you only want the year, you could do:
var query = collection.GroupBy(record => record.DateProperty.Year)
.Select(g => new { Year = g.Key, Name = g.First().Name })
.OrderBy(x => x.Year);
I would use the Distinct and OrderByDescending extensions:
var years = IQueryableObject
.Distinct(x => x.Year).OrderByDescending(x => x.Year).ToList();

Resources