Thanks, folks, that's a very valuable insight. I really love the idea of resolving *OuterRef* via .*join()*, it may help overcome problems I had with reusing *Subquery*. However, I believe *Subquery* exists apart from *QuerySet* for a reason - to separate responsibilities, so should we mix responsibilities now with Subquery / JoinedSubquery?
If we reuse Subquery for *QuerySet.join()*, we need a way to refer to the columns from that Subquery, and either current *.F(...) *method will be added to Subquery, or we need to use named joins ( *QuerySet.join(taxes=Subquery(...))* ). Named joins are problematic, because current implementation of Query can . *resolve_ref()* (*setup_joins* / *names_to_path*) only to related table OR *filtered_relation*. And handling *yet* another case (OR *joined_subquery)* will make the branching even more complex. We could refactor somehow to reduce conditionals usage, but it is not something I believe I am capable of. Yes, it is probably possible to modify existing code, but I am trying to avoid adding new paths and conditions here and there - because over time such changes will lead to hard to understand codebase no one wants to touch. I believe that new behavior is better added via extending, not modifications (open-closed principle). There is already some conditional handling in ORM (i.e. *filtered_relation*, which can be found in many places across whole ORM code, yet it is just one feature (don't get me wrong, it's a valuable contribution, I am just worried of a general direction), and this way of introducing changes will complicate ORM more and more. Instead, the suggested solution relies on existing code, but does not modify it and is relatively small. I will definitely try to create something with *OuterRef*, but I am afraid we will end up with: Subquery which actually contains code of two separate classes, and several conditional branches (i.e. *if subquery.is_joined*) in the QuerySet/Query code. I will come back with new information as soon as I have time (probably by the weekend). Have a nice day, Alexandr. On Tuesday, 7 April 2020 08:39:47 UTC+3, schinckel wrote: > > Great work on this, Alexandr. I've been thinking a lot about doing joins > in Django to subqueries. As you point out, when you are doing several > subquery annotations of the same subquery, just with different columns, > that can really hurt performance. Currently, I've been recommending doing a > JSON object as the subquery column. > > I really like the idea of an explicit join to a subquery, as it can > perform significantly better - in the case where most of the rows share the > same subquery, the database can perform the subquery once per distinct row > joined, rather than once for each row. > > I think, instead of using a `JoinedSubquery`, we should just make it that > a `Subquery`, containing unresolved OuterRef instances, can also be > resolved by doing a `QuerySet.join(Subquery(...))`. > > We could also have a lateral argument that allowed a LATERAL JOIN to a > subquery, but perhaps that's later down the track. > > (Actually, now I think about it, a QuerySet should probably just act as a > Subquery when it's used as one, but perhaps that's too magic). > > Matt. > -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/f32053b3-f4e9-4736-ba64-c15d9a62ba25%40googlegroups.com.