-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Left, right and full outer joins #238
Comments
Could you expand on that? What kind of extra control would you be able to exercise? |
What I mean is having options of what data I get back via the left/right/inner/fullouter, just like when thinking of these type of joins in SQL. The data you get back is flattened out, and determined by which type of join you do. E.g. the left join returns all the Person objects and only the Address objects that match, inner join returns only the Person and Address objects that match, etc. Hopefully I am explaining myself okay. |
So the only thing that would be added is flattening? Why var people = new[]
{
new { PersonId = 1, Name = "Chris" },
new { PersonId = 2, Name = "Joe" },
new { PersonId = 3, Name = "Mike" }
};
var addresses = new[]
{
new { AddressId = 1, PersonId = 2, Street = "Main St" },
new { AddressId = 2, PersonId = 3, Street = "2nd Ave" },
new { AddressId = 3, PersonId = 4, Street = "Broad St" }
};
var query =
from person in people
join address in addresses on person.PersonId equals address.PersonId
select new { person.Name, address.Street };
foreach (var e in query)
Console.WriteLine(e);
// Prints:
// { Name = Joe, Street = Main St }
// { Name = Mike, Street = 2nd Ave } |
After looking at your example I agree with you that I think for the others ( |
Great, so then we are just left with My next question is, have you thought about how this will work with value types? For example, here's a left outer join of two number sequences using standard from x in Enumerable.Range(0, 10)
join y in Enumerable.Range(5, 10) on x equals y into ys
from y in ys.DefaultIfEmpty()
select new { x, y } This will give the output:
What you can see is that the result is rather unsettling as where y was missing, there is now a 0 in the result. Assuming we are working with zero and positive integers only, we can use an overload of from x in Enumerable.Range(0, 10)
join y in Enumerable.Range(5, 10) on x equals y into ys
from y in ys.DefaultIfEmpty(-1)
select new { x, y } The output will be:
The reason I'm going over this is that I think the join methods are going to have signatures that are more complicated than those you initially illustrated (repeated below), in order to account for missing cases: people.LeftJoin(
addresses,
p => p.PersonId,
a => a.PersonId
); It's less of an issue when you are working with references or nullable values where var q = people.LeftJoin(
addresses,
p => p.PersonId,
a => a.PersonId,
p => new { p.Name, Street = (string) null }, // person with no address
(p, a) => new { p.Name, a.Street } // person with address
); Note that there are two functions to determine the projected results. This is better and more explicit than Also, I'm not in favor of introducing a type like
Given this and defaults, your signatures will be a little more involved. I want to make sure that you're on the same page with that because it would be a shame if you make a lot of effort for a PR only to find the end-result to be distasteful (or not what you had in mind) so it's good to discuss and set expectations upfront. For example, for |
Yes, what you are saying makes sense. I am thinking of a signature of something like this for public static IEnumerable<TResult> LeftJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> left,
IEnumerable<TRight> right,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> bothSelector,
Func<TLeft, TResult> leftOnlySelector,
IEqualityComparer<TKey> comparer = null
) And
This handles the cases you mentioned in your last comment, such as:
What are your thoughts on this? Thanks. |
Thanks for working through the questions and glad to see we are on the same page. 👍 I suggest you proceed with 2 PRs, one for |
In terms of consistency of names, we should decide if the outer qualification is necessary. It's not there in |
Yeah, 2 separate PRs make sense to me. I agree that we should use |
I forked the project and made a separate branch. When I load the solution in Visual Studio 2015 it builds successfully, but the |
I actually have the same problem (and in another project of mine too)… However, my Error List pane is empty and the solution builds just fine. I'm guessing this issue has to do with the Do you have the .NET Core tools installed? Have you tried building from the command line by simply running |
I got it working now. Tests run successfully as well. Thanks. |
Overview
I am thinking that it would be helpful to have
LeftJoin
,RightJoin
,InnerJoin
, andFullOuterJoin
methods in MoreLINQ. I know that there is alreadyGroupJoin
andFullGroupJoin
(from MoreLINQ), but I know sometimes I would like a way to have more control over my joins and have them be flattened.I am thinking these new methods could return an IEnumerable of an object such as this:
Below is some sample data (to allow this to be a little more concrete) and examples of what I am thinking as far as calling these new methods and the results they would provide:
Sample Data
LeftJoin
Call
Pseudo-Code Result
RightJoin
Call
Pseudo-Code Result
InnerJoin
Call
Pseudo-Code Result
FullOuterJoin
Call
Pseudo-Code Result
Question/Request
Would this be a welcome contribution to the project right now? I would be happy to work on this in a fork and submit a pull request, but I wanted to first see if you think this would be a positive contribution to the project. Please let me know if you would like to discuss this further. Thank you.
The text was updated successfully, but these errors were encountered: