【问题标题】:django orm equivalent for "group by sth. having every(sth.)"django orm 等效于“按某事分组。拥有每一个(某事)”
【发布时间】:2014-05-30 05:41:27
【问题描述】:

假设我有一个模型“Book”,它包含三个字段:name、author_name(作为字符串)、publish_state。 现在我想找出哪些作者恰好有一本出版的书。这个 sql 查询完全符合我的要求:

SELECT author_name from books GROUP BY author_name HAVING count(name) = 1 and every(publish_state = 'published');

我正在使用 Postgres,正如您可以通过 'every' 子句所说的那样。

有没有办法在 django ORM 中做到这一点?还是我需要为此使用原始查询?

【问题讨论】:

    标签: django django-orm django-postgresql


    【解决方案1】:

    可能有更好的方法,但至少你可以做到以下......

    books = Book.objects.filter(publish_state='published')
    authors = {}
    
    for book in books:
        authors.setdefault(book.author, 0)
        authors[book.author] += 1
    
    rookies = [x for x, y in authors.iteritems() if y == 1]
    

    【讨论】:

    • 是的。这在技术上是正确的,但我正在寻找数据库方法。
    【解决方案2】:

    当你在annotate 之后使用filter() 时,Django 使用have 子句,例如annotate(foo=Count('bar')).filter(foo__gt=3)。像这样添加values_listdistinct,你应该会很好:

    Book.objects.filter(publish_state='published').values_list('author_name',  flat=True).order_by('author_name').annotate(count_books=Count('name')).filter(count_books=1).distinct()
    

    【讨论】:

    • 没有。这是不正确的!您的查询包含那些拥有许多书籍但只有其中一本出版的作者。我需要那些只有一本书并且已经出版的人。
    • 然后将publish_state的过滤器移到注释过滤器之后。
    • 不幸的是(但并不奇怪),Django 将这些过滤器(在 annotate 之后)也放在了 WHERE 子句中,而不是我需要的 HAVING 子句。
    【解决方案3】:

    不幸的是,这个功能在 django 的 ORM 中没有实现,而且我认为不会很快实现,因为它不是一个很常见的查询。

    我不得不使用原始 SQL。你可以在这里找到它: https://docs.djangoproject.com/en/1.7/topics/db/sql/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 2013-07-17
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      相关资源
      最近更新 更多