你可以使用annotate
,extra
或raw
。這裏是你如何使用annotatate
:
books = [a.book_set.latest('pub_date') for a in Author.objects
.annotate(latest=Max('book__pub_date'))
.order_by('-latest')[:5]]
假設作者不必多本書籍與同pub_date
你可以使用extra
這樣的:
sql = '''SELECT MAX(app_book.pub_date)
FROM app_book
WHERE app_book.author_id=app_author.id'''
latest = Author.objects.extra(
select={'latest': sql},
order_by=['-latest'])[:5].values_list('latest')
books = Book.objects.filter(pub_date__in=[x[0] for x in latest]).order_by('-pub_date')
如果使用raw
你能抓住所有使用單個查詢書:
sql = '''SELECT * FROM app_book
WHERE app_book.pub_date IN
(SELECT MAX(app_book.pub_date)
FROM app_book
GROUP BY app_book.author_id)
ORDER BY app_book.pub_date DESC'''
books = list(Book.objects.raw(sql)[:5])
我假設模型如下所示:
class Author(models.Model):
name = models.CharField(max_length=50)
class Book(models.Model):
title = models.CharField(max_length=50)
author = models.ForeignKey(Author)
pub_date = models.DateTimeField()
class Meta:
get_latest_by = 'pub_date'
爲了好玩,我想我應該基準三種方法(使用充滿100K左右僞書DB):
>>> %time annotate()
(0.274) SELECT "app_author"."id", "app_author"."name", MAX("app_book"."pub_date") AS "latest" FROM "app_author" LEFT OUTER JOIN "app_book" ON ("app_author"."id" = "app_book"."author_id") GROUP BY "app_author"."id", "app_author"."name", "app_author"."id", "app_author"."name" ORDER BY "latest" DESC LIMIT 5; args=()
(0.035) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."author_id" = 10 ORDER BY "app_book"."pub_date" DESC LIMIT 1; args=(10,)
(0.036) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."author_id" = 9 ORDER BY "app_book"."pub_date" DESC LIMIT 1; args=(9,)
(0.036) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."author_id" = 8 ORDER BY "app_book"."pub_date" DESC LIMIT 1; args=(8,)
(0.036) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."author_id" = 7 ORDER BY "app_book"."pub_date" DESC LIMIT 1; args=(7,)
(0.040) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."author_id" = 6 ORDER BY "app_book"."pub_date" DESC LIMIT 1; args=(6,)
CPU times: user 0.32 s, sys: 0.15 s, total: 0.47 s
Wall time: 0.47 s
<<< [<Book: Susan>, <Book: Yasmin>, <Book: Carl>, <Book: Benny>, <Book: George>]
>>> %time extra()
(0.445) SELECT (SELECT MAX(app_book.pub_date)
FROM app_book
WHERE app_book.author_id=app_author.id) AS "latest" FROM "app_author" ORDER BY "latest" DESC LIMIT 5; args=()
(0.045) SELECT "app_book"."id", "app_book"."title", "app_book"."author_id", "app_book"."pub_date" FROM "app_book" WHERE "app_book"."pub_date" IN (2038-11-25 11:33:30.425836, 2038-11-24 11:33:30.424598, 2038-11-23 11:33:30.423435, 2038-11-22 11:33:30.422227, 2038-11-21 11:33:30.421045) ORDER BY "app_book"."pub_date" DESC; args=(u'2038-11-25 11:33:30.425836', u'2038-11-24 11:33:30.424598', u'2038-11-23 11:33:30.423435', u'2038-11-22 11:33:30.422227', u'2038-11-21 11:33:30.421045')
CPU times: user 0.32 s, sys: 0.18 s, total: 0.50 s
Wall time: 0.50 s
<<< [<Book: Susan>, <Book: Yasmin>, <Book: Carl>, <Book: Benny>, <Book: George>]
>>> %time raw()
(0.279) SELECT * FROM app_book
WHERE app_book.pub_date IN
(SELECT MAX(app_book.pub_date)
FROM app_book
GROUP BY app_book.author_id)
ORDER BY app_book.pub_date DESC; args=()
CPU times: user 0.19 s, sys: 0.09 s, total: 0.28 s
Wall time: 0.28 s
<<< [<Book: Susan>, <Book: Yasmin>, <Book: Carl>, <Book: Benny>, <Book: George>]
寫一個存儲過程,並從中檢索數據集... –