【问题标题】:Subquery in select Django选择 Django 中的子查询
【发布时间】:2013-11-07 16:30:06
【问题描述】:

试图在 Django 中通过 Postgresql 运行一个复杂的查询。

这些是我的模型:

class Link(models.Model):
    short_key = models.CharField(primary_key=True, max_length=8, unique=True, blank=True)
    long_url = models.CharField(max_length=150)

class Stats_links_ads(models.Model):
    link_id = models.ForeignKey(Link, related_name='link_viewed', primary_key=True)
    ad_id = models.ForeignKey(Ad, related_name='ad_viewed')
    views = models.PositiveIntegerField()
    clicks = models.PositiveIntegerField()

我想使用 Django ORM 运行一个查询,该查询将转换为如下内容:

select a.link_id, sum(a.clicks), sum (a.views), (select long_url from links_link b where b.short_key = a.link_id_id)
from links_stats_links_ads a
group by a.link_id_id;

如果我排除了我需要的 long_url 字段,我可以运行此代码,它会起作用:

Stats_links_Ads.objects.all().values('link_id').annotate(Sum('views'), Sum('clicks'))

不知道如何在select语句中添加子查询。

谢谢

【问题讨论】:

    标签: django postgresql django-models django-orm


    【解决方案1】:

    您可以使用查询集的query attribute 查看查询背后的原始 sql。

    例如,使用 select_related 查看我的第一个答案背后的 sql,很明显生成的 sql 没有按预期运行,访问 long_url 会导致额外的查询。

    采取 2

    您可以像这样使用双下划线符号来跟踪关系

    qs = Stats_links_ads.objects
            .values('link_id', 'link_id__long_url')
            .annotate(Sum('views'), Sum('clicks'))
    str(qs.query)
    'SELECT 
        "stackoverflow_stats_links_ads"."link_id_id", 
        "stackoverflow_link"."long_url", 
        SUM("stackoverflow_stats_links_ads"."clicks") AS "clicks__sum",
        SUM("stackoverflow_stats_links_ads"."views") AS "views__sum"
    FROM "stackoverflow_stats_links_ads" 
        INNER JOIN "stackoverflow_link" 
        ON ("stackoverflow_stats_links_ads"."link_id_id" = "stackoverflow_link"."short_key")
    GROUP BY 
        "stackoverflow_stats_links_ads"."link_id_id", 
        "stackoverflow_link"."long_url"'
    

    我没有处理任何数据,所以我没有验证它,但是 sql 看起来是正确的。

    拍1

    不起作用

    你不能用.select_related吗? [docs]

    qs = Stats_links_Ads.objects.select_related('link')
         .values('link_id').annotate(Sum('views'), Sum('clicks'))
    str(qs.query)
    'SELECT 
        "stackoverflow_stats_links_ads"."link_id_id", 
        SUM("stackoverflow_stats_links_ads"."clicks") AS "clicks__sum", 
        SUM("stackoverflow_stats_links_ads"."views") AS "views__sum" 
    FROM "stackoverflow_stats_links_ads" 
    GROUP BY "stackoverflow_stats_links_ads"."link_id_id"'
    

    【讨论】:

    • 嘿,想到了 select_related 选项,但这与使用 annotate 时无关,因为我没有得到对象。 SQL 明智的意思是,我不是在 select 语句中使用子查询,而是在 where 子句中添加一个简单的连接,如果我只想按一个字段 (link_id) 分组,这不是可选的
    • 注意:在使用基于总和的注释(Sum、Avg 等)和不同的多连接(多对*)时要小心。由于初始结果集不会不同,因此由于重复的行,总和将不准确。见这里:code.djangoproject.com/ticket/10060
    猜你喜欢
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 2015-08-01
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多