Reputation: 1
I have to return the average length of the most sold tracks in a certain time, using 3 models i manage to form an sql query that looks something like this
select AVG(t.Milliseconds) as lengthTrack
from invoice_items as il
join invoices as i on i.invoiceid = il.invoiceid
join tracks as t on t.TrackId = il.TrackId
where i.InvoiceDate between '2012-01-01' and '2013-12-31'
order by il.Quantity DESC LIMIT 10
I manage to come up with this as I got really confused about how to join both tables in order to get the average length track of the 10 most sold ones :
start_date = datetime.date(2012, 01, 01)
end_date=datetime.date(2013, 12, 31)
InvoiceItem .objects.filter(ino_date__range=(start_date, end_date),)
model.py
class Invoice(models.Model):
id = models.AutoField(primary_key=True, db_column='InvoiceId')
customerid = models.ForeignKey(Customer, db_column='CustomerId', on_delete=models.CASCADE)
invoicedate = models.DateTimeField(db_column='InvoiceDate')
billingaddress = models.TextField(max_length=70, db_column='BillingAddress', blank=True, null=True)
billingcity = models.TextField(max_length=40, db_column='BillingCity', blank=True, null=True)
billingstate = models.TextField(max_length=40, db_column='BillingState', blank=True, null=True)
billingcountry = models.TextField(max_length=40, db_column='BillingCountry', blank=True, null=True)
billingpostalcode = models.TextField(max_length=10, db_column='BillingPostalCode', blank=True, null=True)
total = models.TextField(db_column='Total')
class Track(models.Model):
id = models.AutoField(primary_key=True, db_column='TrackId')
playlist = models.ManyToManyField(Playlist, through='PlaylistTrack')
name = models.TextField(db_column='Name', max_length=200)
albumid = models.ForeignKey(Album, db_column='AlbumId', blank=True, null=True, on_delete=models.CASCADE)
mediatypeid = models.ForeignKey(MediaType, db_column='MediaTypeId', on_delete=models.CASCADE)
genreid = models.ForeignKey(Genre, db_column='GenreId', blank=True, null=True, on_delete=models.CASCADE)
composer = models.TextField(db_column='Composer', blank=True, null=True, max_length=220)
milliseconds = models.IntegerField(db_column='Milliseconds')
bytes = models.IntegerField(db_column='Bytes', blank=True, null=True)
unitprice = models.DecimalField(db_column='UnitPrice', max_digits=5, decimal_places=2)
class InvoiceItem(models.Model):
id = models.AutoField(primary_key=True, db_column='InvoiceLineId')
invoiceid = models.ForeignKey(Invoice, db_column='InvoiceId', on_delete=models.CASCADE)
trackid = models.ForeignKey(Track, db_column='TrackId', on_delete=models.CASCADE)
unitprice = models.DecimalField(db_column='UnitPrice', max_digits=5, decimal_places=2)
quantity = models.IntegerField(db_column='Quantity')
serialerzs.py
class InvoiceSerialer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Invoice
fields = ('id', 'total')
class InvoiceItemSerialer(serializers.HyperlinkedModelSerializer):
class Meta:
model = InvoiceItem
fields = '__all__'
class TrackSerialer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Track
fields = '__all__'
in the views do i need to add the 3 serializers in erializer_class? i also wanna ask if my query right ?
Upvotes: 0
Views: 298
Reputation: 396
Getting the most sold between dates is going to be a matter of annotating the tracks with how many times they were sold between those dates.
from django.db.models import Count, Q
top_ten_selling_tracks = Track.objects.annotate(
sales_count=Count(
'invoice_item', # count the number of invoices that point to this track
filter=Q(invoiceid__invoicedate__range=(start_date, end_date)) # only count them if the associated invoice falls in the appropriate range
)).order_by(
'-sales_count' # order them by sales descending, to get the top 10
)[:10] # take the top ten tracks
The average can be done in python (Django can aggregate over a queryset easily, but with your limit constraint it's probably easier to just
return avg(t.milliseconds for t in top_ten_selling_tracks)
Upvotes: 1