Better Alternate 而不是在 Django ORM 中使用链式联合查询

Better Alternate instead of using chained union queries in Django ORM

我需要在 Django ORM 中实现类似的功能:

(SELECT * FROM `stats` WHERE MODE = 1 ORDER BY DATE DESC LIMIT 2) 
UNION
(SELECT * FROM `stats` WHERE MODE = 2 ORDER BY DATE DESC LIMIT 2)     
UNION                                                                       
(SELECT * FROM `stats` WHERE MODE = 3 ORDER BY DATE DESC LIMIT 2)
UNION                                                                         
(SELECT * FROM `stats` WHERE MODE = 6 ORDER BY DATE DESC LIMIT 2) 
UNION
(SELECT * FROM `stats` WHERE MODE = 5 AND is_completed != 3 ORDER BY DATE DESC)                                                                           
# mode 5 can return more than 100 records so NO LIMIT here 

为此我写了这个:

query_run_now_job_ids = Stats.objects.filter(mode=5).exclude(is_completed=3).order_by('-date')
list_of_active_job_ids = Stats.objects.filter(mode=1).order_by('-date')[:2].union(
                            Stats.objects.filter(mode=2).order_by('-date')[:2],
                            Stats.objects.filter(mode=3).order_by('-date')[:2],
                            Stats.objects.filter(mode=6).order_by('-date')[:2],
                            query_run_now_job_ids)

但不知何故 list_of_active_job_ids 返回的是无序的,即 list_of_active_job_ids.ordered returns False 由于当这个查询被传递给 Paginator class 它给出:

UnorderedObjectListWarning: 
Pagination may yield inconsistent results with an unordered object_list  

我已经在 models.py

的 class Meta 中设置了顺序
class Meta:
        ordering = ['-date']

没有分页器查询工作正常,页面加载但使用分页器,视图从不加载它一直在加载。

有没有更好的替代方案可以在不使用联合链的情况下实现这一目标。

所以我为上面的 mysql 查询尝试了另一个替代方法,但我陷入了另一个问题,无法为 mode = 5[ 编写条件=45=] 在这个查询中:

SELECT  
    MODE ,
    SUBSTRING_INDEX(GROUP_CONCAT( `job_id` SEPARATOR ',' ),',',2) AS job_id_list,
    SUBSTRING_INDEX(GROUP_CONCAT( `total_calculations` SEPARATOR ',' ),',',2) AS total_calculations
FROM `stats`            
ORDER BY DATE DESC 

即使我能够编写此查询,它也会将我带到另一个具有挑战性的情况,即将此查询转换为 Django ORM。

为什么我的查询没有被排序,即使我已经在 Class Meta 中设置了它。

此外,如果不是这个查询,是否有更好的替代方法来实现这个?

帮助将不胜感激! .

我正在使用 Python 2.7 和 Django 1.11。

虽然子查询可能是有序的,但生成的联合数据却不是。您需要明确定义顺序。

from django.db import models

def make_query(mode, index):
    return (
        Stats.objects.filter(mode=mode).
        annotate(_sort=models.Value(index, models.IntegerField())).
        order_by('-date')
    )

list_of_active_job_ids = make_query(1, 1)[:2].union(
     make_query(2, 2)[:2],
     make_query(3, 3)[:2],
     make_query(6, 4)[:2],
     make_query(5, 5).exclude(is_completed=3)
).order_by('_sort', '-date')

我所做的只是添加一个新的文字值字段 _sort,每个子查询都有不同的值,然后在最后的代码中按它排序 query.The 代码的其余部分只是为了减少复制。如果不是那个 mode=6 子查询,它会更干净。