【问题标题】:Django - joining a nested group_byDjango - 加入嵌套的 group_by
【发布时间】:2021-01-25 16:49:36
【问题描述】:

我想从通过第三个表(KeyModel)链接的 2 个表(A、B)中聚合数据。 我知道 Django 的查询集方法 'values' 和 'annotate' 的使用,并设法用它创建了复杂的查询,但这个我卡住了:

model A
    key = ForeignKey(KeyModel)
    value_1 = IntegerField()

model B
    key = ForeignKey(KeyModel)
    value_2 = IntegerField()

model KeyModel
    <some irrelevant fields>

data - model/ table A
key_id | value_1
4711 | 100

data - model/ table B
key_id | value_2
4711 | 100
4711 | 100
4711 | 100

我喜欢实现这个结果:

-- key_id | sum_value_1 | sum_value_2
-- 4711 | 100 | 300

以下django/python代码生成错误的SQL:

qs = table_a.objects.filter(key_id=4711)
qs = qs.values('key_id')
qs = qs.annotate(sum_value_1=SUM(value_1))
qs = qs.annotate(sum_value_2=SUM(KeyModel__table_b__value_2))

会生成

SELECT 
    A.key_id,
    SUM(A.value_1) AS sum_value_1,
    SUM(B.value_2) AS sum_value_2
FROM table_a A
JOIN table_b B ON B.key_id=A.key_id
WHERE A.key_id=4711
GROUP BY A.key_id;

但这不是我需要的。连接将表 A 中的行增加三倍,所以结果是

key_id | sum_value_1 | sum_value_2
4711 | 300 | 300

“稍微”改变的 SQL 正在做我想做的事:

SELECT 
    A.key_id,
    SUM(A.value_1) AS sum_value_1,
    V.sum_value_2
FROM table_a A
JOIN (
    SELECT
        B.key_id,
        SUM(B.value_2) AS sum_value_2
    FROM table_b B
    GROUP BY B.key_id   
) V ON V.key_id=A.key_id
WHERE A.key_id=4711
GROUP BY A.key_id, V.sum_value_2;

但是,如何使用 django 查询集方法来做到这一点? (顺便说一句:django 2.2) 我很确定这是我错过的一个小细节 - 但在多次翻转各种代码片段后我迷路了 - 感谢任何提示。

【问题讨论】:

    标签: django join group-by django-queryset


    【解决方案1】:

    SubQuery 是要查找的主题。 我这样解决了这个问题:

    sq = table_b.objects.filter(key_id=OuterRef('key_id'))
    sq = sq.values('key_id')
    sq = sq.annotate(sum_value_2=Sum('value_2', output_field=IntegerField()))
    
    qs = table_a.objects.filter(key_id=4711)
    qs = qs.values('key_id')
    qs = qs.annotate(sum_value_1=Sum('value_1', output_field=IntegerField()))
    qs = qs.annotate(sum_value_2=Subquery(queryset=sq.values('sum_value_2'), output_field=IntegerField()))
    

    它并不能完全生成我上面需要的 SQL,但它会返回我想要的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-19
      • 2018-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多