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();
Related
I guess there must be an easy way, but not finding it. I would like to check whether a list of items, appear (completely or partially) in another list.
For example: Let's say I have people in a department as List 1. Then I have a list of sports with a list of participants in that sport.
Now I want to count, in how many sports does all the people of a department appear.
(I know some tables might not make sense when looking at it from a normalisation angle, but it is easier this way than to try and explain my real tables)
So I have something like this:
var peopleInDepartment = from d in Department_Members
group d by r.DepartmentID into g
select new
{
DepartmentID = g.Key,
TeamMembers = g.Select(r => d.PersonID).ToList()
};
var peopleInTeam = from s in Sports
select new
{
SportID = s.SportID,
PeopleInSport = s.Participants.Select(x => x.PersonID),
NoOfMatches = peopleInDepartment.Contains(s.Participants.Select(x => x.PersonID)).Count()
};
The error here is that peopleInDepartment does not contain a definition for 'Contains'. Think I'm just in need of a new angle to look at this.
As the end result I would like print:
Department 1 : The Department participates in 3 sports
Department 2 : The Department participates in 0 sports
etc.
Judging from the expected result, you should base the query on Department table like the first query. Maybe just include the sports count in the first query like so :
var peopleInDepartment =
from d in Department_Members
group d by r.DepartmentID into g
select new
{
DepartmentID = g.Key,
TeamMembers = g.Select(r => d.PersonID).ToList(),
NumberOfSports = Sports.Count(s => s.Participants
.Any(p => g.Select(r => r.PersonID)
.Contains(p.PersonID)
)
)
};
NumberOfSports should contains count of sports, where any of its participant is listed as member of current department (g.Select(r => r.PersonID).Contains(p.PersonID))).
I have an ASP.NET application that talks to an SQL database containing 4 tables:
Cities
States
StatesCities (maps Cities<=>States)
Customers (which stores the ID of the City they live in)
I need to get a count of how many customers live in a particular state. I can achieve this with the following SQL query:
select count(*) from Customers where CityID in
(
select sc.CityID from StatesCities sc, States s
where sc.StateID = s.StateID AND s.Name = 'Texas'
)
How can I express the equivalent of this query in LINQ, either using the EF or LINQ to SQL?
With the EF approach I've made it as far as:
var cities = db.Cities.Where(c => c.States.Any(s => s.Name == "Texas"));
but I'm not sure how to do the Customer/CityID match and count.
You could do something like this:
int CustomersCount=db.Customers.Count(c=>c.City.State.Name=="Texas");
or
var cities = db.Cities.Where(c => c.States.Any(s => s.Name == "Texas"));
int customersCount=Customers.Count(d=>cities.Any(x=>d.CityID==x.CityID);
#216 got me on the right track with the first suggestion, but because a City can exist in more than one State I needed to tweak the statement slightly:
int customersCount = db.Customers.Count(c => c.City.States.Any(s => s.Name == "Texas"));
I have 3 tables: DiaryPosts, DiaryImpressions, Impressions.
Impressions is a small list with some fields: 'like', 'dislike', 'agree', 'disagree'. The user can vote according to what he thinks about the post.
DiaryImpressions is the table that handles the relationship between the posts and the users who vote.
My problem is, I have to count results of each impression vote for each post, so maybe for one post 13 users voted for like, 2 for dislike, 34 agree and 1 disagree.
I have no idea how to perform the query in some way I can get this specific count results for each impression.
Can anyone help me with that?
You can do this via the GroupBy method. It allows you to automatically "group" the elements based on the impression, and count the results per group.
var post(from c in posts selec c)
string post1like;
string post2dislike;
string postagree3;
string postdisagree3;
foreach (var item in posts)
{
var ipressionslike=(from c in imressions where impressioid=item.id where c.impressionID='LIKE' select c.userID).Tolist()
var ipressionsdislike=(from c in imressions where impressioid=item.id where c.impressionID='disLIKE' select c.userID).Tolist()
var ipressionslike=(from c in imressions where impressioid=item.id where c.impressionID='LIKE' select c.userID).Tolist()
var ipressionsagree=(from c in imressions where impressioid=item.id where c.impressionID='disLIKE' select c.userID).Tolist()
post1like+=item.id+""+ipressionsdislike.count;
post2dislike+=item.id+""+ipressionslike.count;
postagree3+=item.id+""+ipressionsagree.count;
}
it should count the impressions for each post and count the amount of users that like or dislike so if you have 30 people dislike for each post it should get them I cannot see your table structure but I hope it will help or point you somewhere
I have to guess but here is what I think the SQL would look like:
SELECT I.Name, COUNT(I.Name)
FROM DairyPosts P
JOIN DairyImpressions DI ON P.ID=DI.DairyID
JOIN Impressions I ON DI.ImpressionsID = I.ID
And what the linq would look like:
List<Dairy> dairyposts = GetDairyPosts();
var impressionCounts =
from p in dairyposts
group p by p.ImpressionName into g
select new { Type = g.Key, ImpressionCount = g.Count() };
Of course I have to assume your list is created a certain way, if you can post how your list is actually created that would help. (As I said in the comments)
To save multiple DB calls, and since it is from the same table, I'm looking for one of the fields in my linq query to return an object with 2 fields that are IEnumerable.
I wrote some pseudeocode here that should illustrate what I'm trying to do, but its not valid Linq code. Anyone know how to make this work? (Fred & Joe will both be IEnumerable)
var c = from jobs in model.jobView
select jobs.JobID, jobs.NameID, new
{
Fred = from j in model.jobView
select jobs.Field1,
Joe = from k in model.jobView
select jobs.Field2
};
You want to create an anonymous type and then create another anonymous type within it.
I am guessing there is a typo in your two collections where you use j and k, but select with jobs
var c = from jobs in model.jobView
select new
{
jobs.JobID,
jobs.NameID,
TwoObjects = new
{
Fred = from j in model.jobView
select jobs.Field1,
Joe = from k in model.jobView
select jobs.Field2
}
};
In another posting: Does Linq-To-Sql support composable queries there was discussion on how to compose/concat where clauses dynamically. This appears to be done with an "AND" (i.e. the first where clause and the second where clause are joined by an AND). What I am wondering is if there is a way to compose Linq queries with an OR.
Example:
var people = from p in Person
where p.age < 18
select p
var otherPeople = from p in people
where p.firstName equals "Daniel"
select p
This gives people with a first name of "Daniel" and that are under 18. I'm looking for the syntax to join these to find people who have a first name of "Daniel" or are under 18.
Note: I am using ADO.net Data Services so I do not have .Contains() available to me.
EDIT: The Union Suggestion (by Garry Shutler) is exactly what I am looking for functionality-wise. I did run into two possible issues with it:
It looks like it would make multiple database hits if I was to do a third condition (union seems to take an IEnumerable as its parameter) - I was hoping to build up multiple AND and OR statements in code and then execute one request.
Union is not supported by ADO.Net Data Services (very disappointing)
Is what you want as simple as:
var people = from p in Person
where p.age < 18 || p.firstName == "Daniel"
select p;
or have you just given a simple example?
In which case you can use:
var under18 = from p in Person
where p.age < 18
select p;
var daniels = from p in Person
where p.firstName == "Daniel"
select p;
var combined = under18.Union(daniels);
LinqToSql may be intelligent enough to convert that to an OR but I'm not so sure.
What about using PredicateBuilder by Joe Albahari?
var predicate = PredicateBuilder.False<Person>();
predicate = predicate.Or(p => p.age < 18);
predicate = predicate.Or(p => p.firstName == "Daniel");
var query = Person.Where(predicate);
The predicate option is the way to go. The Union option DOES NOT build good sql. Reference http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/925b245d-5529-4a64-8cd4-4bc83ee6fe7a/
I wrote about how to achieve queries which search for a key value within a set on my blog .
Here are the relevant links.
Contains Operations in ADO.NET Data Services Part I
Contains Operations in ADO.NET Data Services Part II
Using this , you can write queries which look like this
//The set in which we have to search for a match
List<string> citiesIWillVisit = new List<string>() {"London","Berlin","Prague"};
var customersAround = nwContext.Customers
.IsIn<Customers>(citiesIWillVisit, c=> c.City);
foreach (Customers localCustomer in customersAround) {
System.Console.WriteLine(localCustomer.ContactName);
}