When I checked the queries generated, it appears that the isnull
lookups result in INNER JOINs for my case.



On 6 Eylül, 16:38, omat <[EMAIL PROTECTED]> wrote:
> Malcolm, these are the models:
>
> class Question(models.Model):
>     question = models.CharField(max_length=150)
>     slug = models.SlugField(max_length=150,
>                             editable=False)
>     verb = models.ForeignKey(Verb)
>     added = models.DateTimeField(editable=False)
>     user = models.ForeignKey(User)
>
> class Answer(models.Model):
>     question = models.ForeignKey(Question)
>     answer = models.PositiveSmallIntegerField(choices=((1, 'Yes'), (2,
> 'No')))
>     user = models.ForeignKey(User)
>     added = models.DateTimeField(editable=False)
>
> On 6 Eylül, 16:34, omat <[EMAIL PROTECTED]> wrote:
>
> > Thanks for clarifying this with such a detailed explanation.
>
> > I took the first way you have suggested and get things working with
> > the following manager:
>
> > class QuestionManager(models.Manager):
> >     def get_not_answered(self):
> >         cursor = connection.cursor()
> >         cursor.execute("""SELECT questions_question.id
> >                           FROM questions_question
> >                               LEFT JOIN questions_answer
> >                               ON questions_question.id =
> > questions_answer.question_id
> >                           GROUP BY questions_question.id,
> > questions_answer.id
> >                           HAVING questions_answer.id IS NULL""")
> >         rows = cursor.fetchall()
> >         ids = [row[0] for row in rows]
> >         cursor.close()
> >         return self.filter(id__in=ids)
>
> > Regards,
> > oMat
>
> > On 6 Eylül, 15:59, "Russell Keith-Magee" <[EMAIL PROTECTED]>
> > wrote:
>
> > > On 9/6/07, omat <[EMAIL PROTECTED]> wrote:
>
> > > > Hi,
>
> > > > For Question & Answer models:
>
> > > > Question.objects.filter(answer__isnull=False)
>
> > > > returns the set of questions that has at least one answer, but:
>
> > > > Question.objects.filter(answer__isnull=True)
>
> > > > does not return the questions that has no answer.
>
> > > > Am I missing something?
>
> > > Somewhat. The problem is that 'isnull' isn't doing what you think it does.
>
> > > When you run Question.objects.filter(answer__isnull=True), this gets
> > > turned into an SQL query something like:
>
> > > SELECT Question.* from Question INNER JOIN Answer WHERE Question.id =
> > > Answer.question_id WHERE Answer.id IS NULL
>
> > > In evaluating this query, this generates an internal table containing
> > > the columns:
> > > Question.id
> > > Question.field1
> > > Question.field2,
> > > ...
> > > Answer.id
> > > Answer.field1
> > > Answer.field2
>
> > > This internal table is then truncated, and only the Question columns
> > > are returned to create Question Django objects.
>
> > > This internal table will contain a row for every Question+Answer pair
> > > where the answer points at the question. If there is no answer to join
> > > with a question, then there will be no answer in the result set.
>
> > > Hence, when you ask for answer__isnull=False - you get all the rows
> > > that are returned. If you ask for answer__isnull=True, you get nothing
> > > - because there can't be an answer-null row that is joined with a
> > > Question.
>
> > > Now - I'm sure the next question is "how to I get all questions that
> > > have at least one answer".
> > > The best SQL way to do this is with an aggregate clause, exploiting
> > > GROUP BY and HAVING to establish how many joined objects exist.
> > > However, Django doesn't currently have good support for aggregate
> > > clauses (something I'm hoping to rectify soon).
>
> > > An alternate approach is to do it in two steps: get a list of all
> > > answers, find the unique question ids (using distinct() and values()
> > > clauses), and then ask for Question.objects.filter(id__in=[list of
> > > ids]), or Question.objects.exclude(id__in=[list of ids]).
>
> > > Yours,
> > > Russ Magee %-)


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to