我有以下表格:
公寓
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 的实际等价查询是什么,子查询效率不高。