2017-08-15 60 views
0

有沒有使用Django的ORM編寫這個原始查詢的方法?我試圖避免使用原始查詢,因爲我想對生成的查詢運行其他過濾器。Django:在生成的聯合查詢上運行查詢

我將展示我目前正在做的事情,可能是錯誤的,但是我想要的最終結果是有一個收件箱,它首先顯示頂部發生了一些新操作的條目,然後列出所有其他條目他們的提交日期。

SELECT result.id, 
max(result.submit_date) submit_date, 
FROM (
    (SELECT 
    table_A.submit_date, 
    table_A.id, 
    FROM table_A INNER JOIN table_B ON 
    (table_A.domain_id = table_B.id) WHERE 
    (table_B.company_id = 3 AND table_A.deleted = FALSE)) 

    UNION 

    (SELECT 
    (time) AS submit_date, 
    (table_C.table_A_id) AS id, 
    FROM table_C INNER JOIN table_A ON 
    (table_C.table_A_id = table_A.id) WHERE 
    (table_C.verb_type IN (8, 9, 14) AND 
    table_C.company_id = 3 AND table_A.deleted = FALSE)) 
) result 

GROUP BY result.id ORDER BY 2 DESC; 

UPDATE: 這裏是我的模型:

#inbox entries 
class table_A(models.Model): 
    domain = models.ForeignKey(table_B) 
    submit_date = models.DateTimeField(auto_now_add=True) 
    deleted = models.BooleanField(default=False) 


#domain entries 
class table_B(models.Model): 
    company = models.ForeignKey(table_D) 
    domain = models.CharField(max_length=50) 
    active = models.BooleanField(default=True) 


#action entries associated with table_A (inbox entries) 
class table_C(models.Model): 
    GAMMA = 0 
    OMEGA = 1 
    PHI = 8 
    CHI = 9 
    SIGMA = 14 
    VERB_CHOICE = (
    (GAMMA, 'action gamma'), 
    (OMEGA, 'action omega'), 
    (PHI, 'action phi'), 
    (CHI, 'action chi'), 
    (SIGMA, 'action sigma'), 
) 
    company = models.ForeignKey(table_D) 
    active = models.BooleanField(default=True) 
    ref_t_A = models.ForeignKey(table_A) 
    verb_type = models.SmallIntegerField(
    choices=VERB_CHOICES, 
    default=GAMMA, 
    db_index=True 
) 
    time = models.DateTimeField(
    verbose_name='date of entry creation', 
    auto_now_add=True, 
    db_index=True 
) 

# company entries 
class table_D(models.Model): 
    name = models.CharField(max_length=100) 
    create_date = models.DateTimeField(
    verbose_name='date account created', 
    auto_now_add=True 
    ) 
    active = models.BooleanField(default=True) 

到目前爲止,我可以(上項行動)使用Django的ORM表-A(收件箱項)和table_C之間建立一個聯盟,但隨後我想要執行外部選擇或其他方法來完成此操作,以便按照我需要的方式對最終結果進行排序,並將新修改的條目根據其操作日期列在頂部,其餘部分以下列出的條目基於他們的提交日期(因爲他們還沒有與他們相關的動作):

x = table_A.values_list('submit_date', 'id',) 
y = table_C.objects.filter(
    company_id=2, 
    verb_type__in=[ 
    table_C.PHI, 
    table_C.CHI, 
    table_C.SIGMA 
    ] 
    ref_t_A__deleted=False 
).extra(
    select={ 
    'id': 'ref_t_A_id', 
    'submit_date': 'time', 
    } 
).values_list('id', 'submit_date',) 

z = x.union(y) 

原始查詢的目的是通過table_C中與其關聯的最新操作對table_A中的條目進行排序,如果沒有與table_C關聯的操作,則使用submit_date。一旦我得到了與table_A中的條目關聯的最新操作或submit_date,我想根據最新操作或submit_date的日期對結果進行排序。

我想在z上運行過濾器,以及任何其他操作,我會好像它是來自table_A模型的查詢集。

+1

請告訴你模型,並添加信息你想要什麼結果。 –

+0

好吧@Bear Brown,我更新了所有內容,我絕對感謝您提供幫助我解決這個問題的任何見解,如果您有更多的信息,請不要猶豫,再次感謝您。 – rasec

回答

0

我無法找到一個乾淨的解決方案,但在這裏,我與Python

額外的結合QS真實數據庫名

qs = table_A.objects.filter(
    deleted=False, domain__company=3).values('submit_date', 'id') 

qs2 = table_C.objects.extra(
    select={'id': 'table_a.id', 'submit_date': 'time'} 
    ).filter(
    verb_type__in=(8, 9, 14), company=3, ref_t_A__deleted=False 
    ).values('submit_date', 'id') 

union_qs = list(qs) + list(qs2) 

下一個按日期排序代替表-A - 同如發現最大

sort_qs = sorted(union_qs, key=lambda k: k['submit_date']) 
sort_qs.reverse() 

上完成的刪除重複

result = [] 
result_ids = [] 
for item in sort_qs: 
    pk = item.get('id') 
    if pk not in result_ids: 
     result.append(item) 
     result_ids.append(pk)