首页 > 解决方案 > django左外连接过滤不匹配记录

问题描述

目标是找出调查响应是否没有所有顶级问题的当前答案。

这可以通过获取响应的所有顶级问题来完成,然后过滤掉没有当前答案的问题。

我可以用 SQL 编写它,但是有没有办法可以使用 django 的 QuerySet 接口来实现它?

楷模

class Survey(Model):
  ...

class SurveySection(Model):
  survey = ForeignKey(Survey, related_name='survey_sections')

class SurveyQuestion(Model):
  survey_section = ForeignKey(SurveySection, related_name='survey_questions')
  parent = ForeignKey('self') #questions can be nested

class SurveyResponse(Model):
  survey = ForeignKey(Survey, related_name='survey_responses')

class SurveyAnswer(Model):
  survey_response = ForeignKey(SurveyResponse, related_name='survey_answers')
  survey_question = ForeignKey(SurveyQuestion, related_name='survey_answer')
  is_current = BooleanField()

SQL

这应该找到响应所针对的调查的所有顶级问题,获取与这些问题匹配的当前答案并删除没有答案的问题。

select * from survey_surveyquestion question
join survey_surveysection section on section.id = question.survey_section_id
join survey_survey survey on survey.id = section.survey_id
join survey_surveyresponse response on response.survey_id = survey.id
left outer join survey_surveyanswer answer on answer.survey_question_id = question.id and answer.is_current = true
where response.id = 16
  and answer.id is null
  and question.parent is null

标签: django

解决方案


您可以采用这种方法:

首先,获取父为 null 的问题数:

top_question_count = SurveyQuestion.objects.filter(parent__is_null=True).count()

然后,在过滤器中使用它:

from django.db.models imprt Count

SurveyResponse.objects.filter(
    survey_answers__survey_question__parent__is_null=True,
    is_current=True
).annotate(
    top_level_questions=Count('survey_answers__survey_question')
).filter(
    top_level_questions=top_question_count
)

推荐阅读