如果结果存在,则用另一个查询的结果过滤一个连接查询

问题描述 投票:0回答:0

我有以下表格:

公寓

class Apartment(models.Model):    
    name = models.CharField(max_length=250)

回顾

class Review(models.Model):
    apartment = models.ForeignKey(Apartment, on_delete=models.CASCADE, null=True)
    review = models.TextField(null=True)
    author = models.CharField(max_length=255, null=True)
    review_date = models.DateField(null=True)

回应

class Response(models.Model):
    response = models.TextField()
    review = models.ForeignKey(Review, on_delete=models.CASCADE)
    responded_on = models.DateTimeField(auto_now_add=True)
    author = models.CharField(max_length=255)

    

注意

class Note(models.Model):
    review = models.ForeignKey(Review, on_delete=models.CASCADE, null=True)
    current_user = models.IntegerField(null=True)
    modified_on = models.DateTimeField(
      auto_now=True,verbose_name='Last Modified on'
    )

未读笔记

class UnreadNote(models.Model):
    current_user = models.IntegerField(null=True)
    review = models.ForeignKey(Review, on_delete=models.CASCADE)
    note = models.ForeignKey(
      Note, on_delete=models.CASCADE, 
      verbose_name='Last Read Note'
    )
    modified_on = models.DateTimeField(
      verbose_name='Modified Date Of Last Read Note'
    )

这是工作正常的原始查询:

SELECT rw.id, a.name apartment_name, p.id property_id, rw.review_date, 
un.modified_on modified_on 
FROM review rw LEFT JOIN response re ON rw.id = re.review_id 
INNER JOIN apartment a ON a.id = rw.apartment_id 
INNER JOIN note n ON n.review_id = rw.id 
AND n.current_user != 321 AND n.current_user IS NOT NULL
WHERE  rw.apartment_id IN (23, 432, 667, 123) 
AND rw.review_date BETWEEN '2023-02-01' AND '2023-04-30' AND 
GROUP BY  rw.id 
ORDER BY rw.review_date desc

现在我想修改上面的原始查询,首先将下面的 ORM 逻辑转换为原始查询,然后组合两个原始查询以获得最终查询:

这是 ORM 逻辑:

def get_note_count_by_review(review_id, user_id, start_date="", end_date=""):
    unread_note = UnreadNote.objects.filter(
       review_id=review_id, current_user=user_id
    ).order_by("-modified_on").first()
    fields = {'review_id': review_id}
    fields.update({
         'modified_on__gt': unread_note.modified_on} if unread_note 
         else {}
    )
    fields.update(
        {'review__review_date__gte': start_date,
        'review__review_date__lt': end_date} 
        if start_date and end_date else {}
    )
    unread_note_count = Note.objects.filter(**fields).exclude(
       current_user=user_id
    ).exclude(
       current_user__isnull=True
    ).count()
    return unread_note_count

我尝试通过将 ORM 逻辑转换为子查询来修改原始查询,并将其添加到原始查询中,这里是最终查询:

SELECT rw.id, a.name apartment_name, p.id property_id, rw.review_date, 
un.modified_on modified_on 
FROM review rw LEFT JOIN response re ON rw.id = re.review_id 
INNER JOIN apartment a ON a.id = rw.apartment_id 
INNER JOIN note n ON n.review_id = rw.id 
AND n.current_user != 321 AND n.current_user IS NOT NULL 
AND modified_on > (SELECT modified_on FROM 
unread_note WHERE current_user=321 ORDER BY modified_on LIMIT 1)
WHERE  rw.apartment_id IN (23, 432, 667, 123) 
AND rw.review_date BETWEEN '2023-02-01' AND '2023-04-30' AND 
GROUP BY  rw.id 
ORDER BY rw.review_date desc

这行不通。我不确定 ORM 的实际等价查询是什么,子查询效率不高。

mysql django django-models django-orm
© www.soinside.com 2019 - 2024. All rights reserved.