【问题标题】:Django LEFT JOIN query with added AND clause: possible?带有 AND 子句的 Django LEFT JOIN 查询:可能吗?
【发布时间】:2015-06-18 05:07:06
【问题描述】:

我正在尝试执行一个包含 LEFT JOIN ON (condition) AND (condition) 的 Django ORM 查询。但是我不知道怎么做额外的AND condition,把JOIN扔了很长很长的路。

使用第二个条件添加 Django 过滤器并没有帮助 - 它最终成为 WHERE 子句而不是 JOIN 中的 AND 子句。

是否可以在 ORM 中加入 ON 条件 AND 条件,还是应该只使用 SQL 语句?如果可以,你是怎么做的?

不管怎样,这是我试图转换为 Django 的 SQL 查询:

SELECT 
  `editions_edition`.`name` AS edition,
  etc
FROM
  `editions_edition` 
INNER JOIN `surveys_survey` 
  ON (`editions_edition`.`survey_id` = `surveys_survey`.`id`) 
INNER JOIN `questions_question` 
  ON (`surveys_survey`.`id` = `questions_question`.`survey_id`) 
INNER JOIN `questionnaires_questionnaire`
  ON(`editions_edition`.`id`=`questionnaires_questionnaire`.`edition_id`) 
INNER JOIN `entities_entity` 
  ON (`entities_entity`.`id` = `questionnaires_questionnaire`.`entity_id`) 
LEFT JOIN `answers_answer` 
  ON (`answers_answer`.`question_id` = `questions_question`.`id`) 
  AND (`answers_answer`.`questionnaire_id` =`questionnaires_questionnaire`.`id`) 
WHERE `editions_edition`.`id` = *VARIABLE HERE* 
  AND `questions_question`.`type` > 99 
ORDER BY `entities_entity`.`name` ASC,`questions_question`.`sort_order` ASC;

难倒我的是 LEFT JOIN。

我的 Django 查询是这样的:

query = Edition.objects
 .filter(questionnaires__edition__survey__questions__type__gte=100)
 .values(
         'name'
        ,'questionnaires'
        ,'questionnaires__entity__name'
        ,'questionnaires__edition__survey__questions'
        ,'questionnaires__edition__survey__questions__name'
        ,'questionnaires__answers__answer')
 .filter(questionnaires__answers__question=F('questionnaires__edition__survey__questions'))

但最后一个过滤器并没有像我希望的那样神奇地插入到 LEFT JOIN 中。

有什么想法吗?

谢谢

约翰

PS 这些模型使用复数related_names 进行反向查找。这些是您在上面的查询集中看到的复数形式。例如:

class Questionnaire(models.Model):
  edition = models.ForeignKey(Edition,related_name='questionnaires')
  entity = models.ForeignKey(Entity)
  last_edited = models.DateTimeField(auto_now_add=False, auto_now=True)

class Question(models.Model):
  name = models.CharField('Item', max_length=255, unique=False, blank=True)
  survey = models.ForeignKey(Survey, related_name='questions')
  type = models.IntegerField(default=100,choices=QUESTION_TYPES)
  ...

class Answer(models.Model):
  question = models.ForeignKey(Question, related_name='answer')
  questionnaire = models.ForeignKey(Questionnaire, related_name='answers')
  answer = models.CharField(max_length=1024,blank=True)

class Edition(models.Model):
  name = models.CharField(max_length=100)
  slug = models.SlugField()
  survey = models.ForeignKey(Survey)
  ...

【问题讨论】:

  • 能否请您提供您的模型(或相关摘录)以及所有外键及其指定选项。
  • 我添加了一些作为示例。反向查找正在工作。我只是无法确定 JOIN ON AND 语句。
  • 你有想过吗? AND 子句?

标签: mysql django


【解决方案1】:

但最后一个过滤器没有像我希望的那样插入到 LEFT JOIN 它会神奇地做到。

不,Django 不是魔术师 :)

如果你使用select_related(),Django ORM 将进行 LEFT JOIN,条件是左侧有一个允许NULL 的外键(它可以为空)。

可能是这样的:

Edition.objects.select_related('questionnaires').filter("//your searching criteria")

“AND条件”仍然存在问题,但我希望我的回答能给你一些线索,如何进一步进行。

这个问题真的很有趣,今晚我会试着修改一下。

编辑:

这里是 Django 文档的相应链接: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.select_related

以下是我在 Google 网上论坛上找到的内容: https://groups.google.com/forum/#!topic/django-users/CjHVVmu-00c

【讨论】:

  • 它会自动为我执行 LEFT JOIN,即使没有 select_related (尽管它是作为 LEFT OUTER JOIN 执行的,我还没有弄清楚我是否可以忍受)。但是没有AND condition,我得到了我想要的行数的平方(或其他东西 - 这是很多额外的行)
  • 在第二次更仔细地阅读您的问题后,我意识到您的问题不是我错误地假设的 LEFT JOIN 的创建。所以我的回答是针对目标的。请对此表示歉意,如果愿意,我会删除它。 AND condition 的问题引起了我的好奇心,今晚我会尝试尝试一下。
猜你喜欢
  • 2015-08-21
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多