【问题标题】:Performing PostgreSQL LEFT OUTER JOINS and CASEs in Django在 Django 中执行 PostgreSQL LEFT OUTER JOINS 和 CASE
【发布时间】:2010-12-24 08:49:04
【问题描述】:

所以我这里有一个相当复杂的 sql 查询。

SELECT links_link.id, links_link.created, links_link.url, links_link.title, links_category.title, SUM(links_vote.karma_delta) AS karma, SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END) AS user_vote
FROM links_link
LEFT OUTER JOIN auth_user ON (links_link.user_id = auth_user.id)
LEFT OUTER JOIN links_category ON (links_link.category_id = links_category.id) 
LEFT OUTER JOIN links_vote ON (links_vote.link_id = links_link.id)
WHERE (links_link.id = links_vote.link_id)
GROUP BY links_link.id, links_link.created, links_link.url, links_link.title, links_category.title
ORDER BY links_link.created DESC
LIMIT 20

我所有的关系都很好(我认为),当我在我的 navicat for postgresql 中运行它时,这个查询非常有效,但是将它变成 Django 可以使用的东西是相当大的挑战。我使用的是 pre-alpha 1.2 开发版本(来自 subversion 存储库),因此我拥有文档中的全套工具。

这是我的笑容模型:

class Category (models.Model):
    created = models.DateTimeField(auto_now_add = True)
    modified = models.DateTimeField(auto_now = True)
    title = models.CharField(max_length = 128)

    def __unicode__(self):
        return self.title

class Link (models.Model):
    category = models.ForeignKey(Category)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add = True)
    modified = models.DateTimeField(auto_now = True)
    fame = models.PositiveIntegerField(default = 1)
    url = models.URLField(max_length = 2048)
    title = models.CharField(max_length = 256)
    active = models.BooleanField(default = True)

    def __unicode__(self):
        return self.title

class Vote (models.Model):
    link = models.ForeignKey(Link)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add = True)
    modified = models.DateTimeField(auto_now = True)
    karma_delta = models.SmallIntegerField(default = 1)

    def __unicode__(self):
        return str(self.karma_delta)

我怎样才能转身

def latest(request):
    links = Link.objects.all().order_by('-created')[:20]
    return render_to_response('links/list.html', {'links': links})

进入上述查询?

我只能使用Aggregation 之类的东西取得一些进展,但如何解决我对 CASE 的使用问题却超出了我的范围。任何帮助将非常感激。我总是更喜欢在框架的内置 ORM 中工作,但如果需要原始 SQL...

【问题讨论】:

    标签: sql django postgresql


    【解决方案1】:

    我目前没有时间尝试对该查询进行完整翻译,但如果 CASE 是您的主要障碍,我现在可以告诉您它本身不支持,您需要使用使用一些原始 SQL 调用 .extra()。比如:

    .extra(select={'user_vote': 'SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END')})
    

    但是,如果这个查询按原样运行良好,为什么还要麻烦将它翻译成 ORM?只是grab a cursor and run it as a SQL query。 Django 的 ORM 故意不是 100% 的解决方案,它公开原始游标 API 是有原因的。

    更新:从 Django 1.2 开始,还有 Manager.raw() 让您可以进行原始 SQL 查询并取回模型对象(感谢 Van Gale)。

    【讨论】:

    猜你喜欢
    • 2019-08-27
    • 2018-08-21
    • 2013-03-14
    • 2012-02-18
    • 2022-09-28
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    相关资源
    最近更新 更多