0

Totally making this up to resemble something similar to what I'm working with:

Let's say I have a SQL table, which has Name, City, and FavoriteColor. I want to do a LINQ query (I prefer method syntax, where possible) that will group all the records in the table by Name and City. That would, of course, group all the records in the table on those two things by using the .GroupBy(...) LINQ extension method.

But, then I want to filter the resulting set down to some given values (i.e. where Name = Joe and City = Miami), which is done in LINQ by adding a .Where(...) method on a grouped set, resulting in SQL as a HAVING clause.

That's easy enough to do when you only have one value for each to filter on, but let's say the method with this query receives a list of names and cities to filter that result set on. (i.e. filter all those grouped records down to only those named "Joe" in "Miami", "John" in "Tampa Bay", et cetera).

Then, to make it even better, I need to get a count of each Name and City group's favorite color.

In SQL, this would look something like this:

SELECT Name, City, COUNT(FavoriteColor)
FROM People
GROUP BY Name, City
HAVING (Name = "Joe" AND City = "Miami") OR (Name = "John" AND City = Tampa Bay")

Note: that HAVING clause has an OR in between the two, which is what's killing me trying to get to work with LINQ. My LINQ is always stitching AND's together, instead of OR's.

As for the LINQ, what I have is:

public IList<ColorCount> GetFavoriteColorCount(IList<SearchValue> searchValues)
{
    var query = _context.People
                     .GroupBy(p => new
                     {
                         p.Name,
                         p.City
                     })
                     .Select(g => new
                     {
                         Name = g.Key.Name,
                         City = g.Key.City
                     });

    foreach (var searchValue in searchValues)
    {
        query = query.Where(r => r.Name == searchValue.Name && r.City == searchValue.City);
    }

    // TODO: Figure how to get the COUNT for Favorite Color mixed into all this, too.

    var result = query.ToList();
}

However, as mentioned earlier, this results in an AND between the HAVING values, instead of an OR, like I need. I know this because I'm using EF's .LogTo(...) method to output the complete SQL being generated and used. I grabbed that output and ran it against the database and, as expected, got 0 results. I manually changed the AND's to OR's and poof I have the results I expect.

Anyway, if I have a table that has, say, 10 "Joe" and "Miami" record combinations, which 7 have a favorite color of yellow and 3 have green. And, it also has 4 "John" and "Tampa Bay" combinations with 2 blue and 2 red for colors, I believe I would have 4 records in the final list that look something like this:

{ "Joe", "Miami", "Yellow", 7 },
{ "Joe", "Miami", "Green", 3 },
{ "John", "Tampa Bay", "Blue", 2 },
{ "John", "Tampa Bay", "Red", 2 }

The 2 questions:

  1. How do I force an OR in the HAVING clause when iterating over the list of search values that get passed into the method?
  2. How do I also get a COUNT of the Favorite Colors?

0 Answers0