考虑下面的例子:在Django创建自定义查询1.8
class Customer(models.Model):
first_name = models.CharField()
last_name = models.CharField()
rental_date = models.DateTimeField()
rented_car = models.ForeignKey(Car)
class Car(models.Model):
color = models.CharField()
reg_no = models.IntegerField()
我希望将全部自驾租赁(假设客户可以不租一路车多,但客户可以租一辆车多次)并且每个组只返回最近的rental_date
的租赁,并访问客户名称和车辆reg_no
。
的SQL会是这个样子:
SELECT * FROM Customer c where rental_date = (SELECT max(rental_date) FROM Customer WHERE rented_car_id = c.rented_car_id);
或像这样:
SELECT *, max(rental_date) from Customer group by rented_car;
将导致查询集就会按照客户FIRST_NAME或汽车reg_no和其他过滤器来分类的可能应用(例如,只获取名称以'A'开头的蓝色汽车或客户)。我已经尝试
事情:
聚合:
from django.db.models Max
Customer.objects.values('rented_car').annotate(max_start_date=Max('rental_date'))
但这返回包含Car
对象的主键的字典。我也需要Customer
的值。修改查询以包含来自Customer
(.values('rented_car', 'first_name')
)的字段将更改SQL并更改最终结果。
我所用的第二种方法是raw
:
Customer.objects.raw("""SELECT * FROM Customer c where rental_date = (SELECT max(rental_date) FROM Customer WHERE rented_car_id = c.rented_car_id)""")
但这返回一个RawQuerySet实例不允许进一步的过滤或排序。此外,Customer.objects.filter(...).raw(...).order_by(...)
将不会工作,因为raw
方法将覆盖过滤。
可能返回查询设置,并允许额外的滤波另一种方法是extra
:
Customer.objects.filter(...).extra(select={
'customer_instances': """SELECT *, max(rental_date) from Customer group by rented_car"""
})
但他总是会返回一个错误(1241, 'Operand should contain 1 column(s)')
。另外,从这个discussion我发现QuerySet.extra(...)将不再支持,而应该使用aggregation
。
您的模型/模式对我来说似乎很奇怪 - 我会在'Car'和'Customer'中使用一个中间的'Rent'模型,日期和外键。 –
谢谢你的回应。但是,这与我正在研究的项目的情况类比。由于NDA协议,我不能提供任何更多的细节,但是,另一种模式不适合。 –
为什么你的项目不接受一个理智的数据库设计?另外,如果你有严格的NDA和东西,那么就会涉及金钱,所以聘请一位熟悉Django和SQL的顾问,并且不要过来请求其他人免费工作。 –