代码之家  ›  专栏  ›  技术社区  ›  Kirill

Django RawSQL注释字段

  •  1
  • Kirill  · 技术社区  · 2 年前

    如何使用RawSQL对字段进行注释?

        sql_query = """
                SELECT 
                    c.id, 
                    COALESCE(SUM((cm.temp_min + cm.temp_max) / 2 - %s), 0) AS gdd
                FROM 
                    agriculture_commune c
                LEFT JOIN 
                    agriculture_communemeteo cm ON c.id = cm.commune_id
                WHERE 
                    cm.date BETWEEN %s AND %s
                GROUP BY 
                    c.id
            """
        communes =  communes.raw(sql_query, [TBASE, start_date, end_date])
    

    如果我试着这样做,它会起作用

    communes.annotate(gdd=RawSQL(sql_query, [TBASE, start_date, end_date]))
    

    我得到错误“子查询必须只返回一列\n行1:…mmune”

    2 回复  |  直到 2 年前
        1
  •  1
  •   user70    2 年前

    正如错误所说,当使用RawSQL注释字段时,您提供的SQL查询每行只应返回一个值,因为它被用作生成注释查询集的更大查询的一部分。

    因此,您需要使用这样一个查询,它只返回一个值:

    SELECT 
        COALESCE(SUM((cm.temp_min + cm.temp_max) / 2 - %s), 0) AS gdd
    FROM 
        agriculture_communemeteo cm
    WHERE 
        cm.commune_id = agriculture_commune.id AND
        cm.date BETWEEN %s AND %s
    

    然后像您所做的那样进行注释:

    communes.annotate(gdd=RawSQL(sql_query, [TBASE, start_date, end_date]))
    
        2
  •  1
  •   willeM_ Van Onsem    2 年前

    不需要使用原始查询,这可以通过以下方式确定:

    from django.db.models import F, Value
    from django.db.models.functions import Coalesce
    
    Commune.objects.filter(communemeteo__date__range=(start_date, end_date)).annotate(
        gdd=Coalesce(
            (F('communemeteo__temp_min') + F('communemeteo__temp_max')) / 2
            - Value(TBASE),
            0,
        )
    )