简体   繁体   English

更好的替代方法,而不是在Django ORM中使用链式联合查询

[英]Better Alternate instead of using chained union queries in Django ORM

I needed to achieve something like this 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 

for which i wrote this : 为此我写了:

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)

but somehow list_of_active_job_ids returned is unordered ie list_of_active_job_ids.ordered returns False due to which when this query is passed to Paginator class it gives : 但是以某种方式返回的list_of_active_job_ids是无序的,即list_of_active_job_ids.ordered返回False,由于此查询传递给Paginator类时,它给出:

UnorderedObjectListWarning: 
Pagination may yield inconsistent results with an unordered object_list  

I have already set ordering in class Meta in models.py 我已经在models.py中的Meta类中设置了排序

class Meta:
        ordering = ['-date']

Without paginator query works fine and page loads but using paginator , view never loads it keeps on loading . 没有paginator查询可以正常工作和页面加载,但是使用paginator时,视图永不加载,它会继续加载。

Is there any better alternate for achieving this without using chain of union . 在不使用联合链的情况下,是否有更好的替代方法来实现此目的

So I tried another alternate for above mysql query but i'm stuck in another problem to write up condition for mode = 5 in this query : 所以我尝试了另一个替代上面的mysql查询,但我陷入另一个问题,在此查询中写出mode = 5的条件:

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 

Even if I was able to write this Query it would lead me to another challenging situation ie to convert this query for Django ORM . 即使我能够编写此查询,也将导致我遇到另一个具有挑战性的情况,即将该查询转换为Django ORM。

So why My Query is not ordered even when i have set it in Class Meta . 那么,即使在Class Meta中设置了我的查询,为什么也没有排序。

Also if not this query , Is there any better alternate for achieving this ? 另外,如果不是此查询,是否还有更好的替代方法来实现这一点?

Help would be appreciated ! 帮助将不胜感激! .

I'm using Python 2.7 and Django 1.11 . 我正在使用Python 2.7和Django 1.11。

While subqueries may be ordered, the resulting union data is not. 虽然可以查询子查询,但不能查询生成的联合数据。 You need to explicitly define the ordering. 您需要明确定义顺序。

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')

All I did was add a new, literal value field _sort that has a different value for each subquery and then ordered by it in the final query.The rest of the code is just to reduce duplication. 我所做的只是添加了一个新的文字值字段_sort ,该字段的每个子查询都具有不同的值,然后在最终查询中对其进行排序。其余代码只是为了减少重复。 It would have been even cleaner if it wasn't for that mode=6 subquery. 如果不是那个mode=6子查询,它甚至会更干净。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM