如何获得一个子查询中FROM子句中的Django ORM

问题描述:

我试图表达使用Django的ORM以下(Postgres的)SQL语句:如何获得一个子查询中FROM子句中的Django ORM

SELECT 
    v.id, v.min_salary, v.max_salary, v.min_weekly_hours, v.max_weekly_hours 
    p.min_start_date, p.max_end_date 
FROM 
    vacancy v, 
    (
     SELECT 
     id, vacancy_id, MIN(start_date) min_start_date, MAX(end_date) AS max_end_date 
     FROM vacancypublication 
     WHERE (active = True AND site_id = 1 AND start_date <= CURRENT_TIMESTAMP) 
     GROUP BY id, vacancy_id 
    ) p 
WHERE 
    p.vacancy_id = v.id AND 
    v.workflow_status = 'A' 
ORDER BY p.min_start_date DESC; 

的问题是,我使用子查询FROM子句(也称为“内联视图”)。

我试过用.extra(tables=['...']),但是Django给语句加了引号,导致SQL无效。我不想诉诸.raw查询。有没有办法做到这一点?也许通过可重用的应用程序,如果核心API不提供方式。

编辑

这是使用(貌似)等效的语句联接:

SELECT 
    v.id, v.code, v.min_salary, v.max_salary, v.min_weekly_hours, v.max_weekly_hours, v.application_email, v.application_url, v.available_positions, 
    MIN(CASE WHEN (p.active = True AND p.site_id = 1 AND p.start_date <= CURRENT_TIMESTAMP) THEN p.start_date ELSE NULL END) AS start_date, 
    MAX(CASE WHEN (p.active = True AND p.site_id = 1) THEN p.end_date ELSE NULL END) AS end_date 
FROM base_vacancy v 
LEFT OUTER JOIN 
    base_vacancypublication p ON v.id = p.vacancy_id 
WHERE v.workflow_status = 'A' 
GROUP BY v.id, v.code, v.min_salary, v.max_salary, v.min_weekly_hours, v.max_weekly_hours, v.application_email, v.application_url, v.available_positions 
HAVING MIN(CASE WHEN (p.active = True AND p.site_id = 1 AND p.start_date <= CURRENT_TIMESTAMP) THEN p.start_date ELSE NULL END) IS NOT NULL 
ORDER BY start_date DESC; 

这是关于〜3倍,速度慢,但它可能写这个使用Django 1.9 ORM方法:

Vacancy.objects.annotate(
    start_date=Min(
     Case(
      When(publication_set__is_active=True, publication_set__site_id=1, publication_set__start_date__lte=Now(), then='publication_set__start_date'), 
      default=None 
     ) 
    ), 
    end_date=Max(
     Case(
      When(publication_set__is_active=True, publication_set__site_id=1, then='publication_set__end_date'), 
      default=None 
     ) 
    ) 
).filter(
    start_date__isnull=False, status=Workflow.APPROVED 
).order_by(
    '-start_date' 
) 
+0

你尝试使用这些表之间的加入? –

+0

我确实这么做了,但这并不是一个简单的表达。每个空缺有多份出版物,并且汇总是有条件的。 我的确看到了(看似)相当的陈述,但速度大约慢了3倍。 – jaap3

+0

我不能为你做到这一点。我会检查出来后。无论如何,你可以尝试对Postgres启动一个原始查询.... –

您可以直接启动查询对Postgres的...

将是种:

+0

我可以做到这一点,但比我会放弃Django ORM – jaap3

+0

@ jaap3的所有好处如何呢? – e4c5