Django RawSQL аннотирует поле

Как аннотировать поле с помощью 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]))

я получил ошибку "подзапрос должен возвращать только один столбец\nLINE 1: ...mmune"

Как указано в ошибке, при использовании 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]))

Нет необходимости использовать необработанный запрос, его можно определить с помощью:

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,
    )
)
Вернуться на верх