It's simple to create subqueries in Django ORM (just use a QuerySet
as part of another query), but is it possible for that subquery to reference fields in the "parent" (outer, main) query?
For a full example of what I'm trying to achieve, see this working SQL Fiddle. I broke it down into two questions (other one here). In this case, I have a model Whole
that represents a value that must be reached. Several Part
s contribute to it with a (calculated) value of their own. I want to retrieve all the Whole
s which has not been completed yet (i.e. the total_value
is different from the sum of individual values).
select w.*
from whole w
where w.total_value != (
select sum(value expression)
from part p
where p.whole_id = w.id
group by p.whole_id
);
I don't know how (or if it's even possible) to do this using Django ORM. I've seen many examples of subqueries using __in
(and could confirm by print qs.query
that the result is indeed ran as a single query), but only when both queries are independent of each other. Here, the subquery is constrained by a field in the parent query (w.id
). I thought of using F()
, Q()
, or even extra
, but can't quite figure out what to do...
Here's a SSCCE, in case anyone want to experiment with it: Download or Browse. It has the same models and data as the SQL fiddle linked above.
Update: for my particular case, I found out there's no need to do a subquery, I can just use group by
and having
(as this SQL Fiddle shows):
q = Q(part__isnull=True) | ~Q(partial=F('total_value'))
qs = Whole.objects.annotate(partial=Sum(...)).filter(q).distinct()
# And if total_value can be zero:
qs = qs.exclude(part__isnull=True, total_value=0)
The general case for subqueries is still unsolved though (short of using some raw SQL, as my answer below shows).