PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Usando l'annotazione della finestra di Django combinata con una clausola distinta

Penso che il problema principale sia che stai mescolando le operazioni che utilizzate nell'annotazione generano un set di query raggruppato come sum con un'operazione che semplicemente crea un nuovo campo per ogni record nel set di query specificato come yesterday_count=Window(expression=Lag("count")) .

Quindi l'ordinazione conta davvero qui. Quindi, quando provi:

WidgetCount.objects.distinct("date").annotate(date=Trunc("time", "day"), yesterday_count=Window(expression=Lag("count")))

Il set di query dei risultati è semplicemente il WidgetCount.objects.distinct ("data") annotato, non viene eseguito alcun raggruppamento.

Suggerirei di disaccoppiare le tue operazioni in modo che diventi più facile capire cosa sta succedendo e notare che stai iterando sull'oggetto Python, quindi non è necessario fare nuove query!

Nota sull'utilizzo dell'operazione SUM come esempio perché viene visualizzato un errore imprevisto con l'operatore FirstValue. Quindi sto postando con Sum per dimostrare l'idea che rimane la stessa. L'idea dovrebbe essere la stessa per il primo valore semplicemente cambiando acc_count=Sum("count") a first_count=FirstValue("count")

for truncDate_groups in Row.objects.annotate(trunc_date=Trunc('time','day')).values("trunc_date")\
                      .annotate(acc_count=Sum("count")).values("acc_count","trunc_date")\
                      .order_by('trunc_date')\
                      .annotate(y_count=Window(Lag("acc_count")))\
                      .values("trunc_date","acc_count","y_count"):
    print(truncDate_groups)

USCITA:

{'trunc_date': datetime.datetime(2020, 1, 20, 0, 0, tzinfo=<UTC>), 'acc_count': 65, 'y_count': None}
{'trunc_date': datetime.datetime(2020, 1, 21, 0, 0, tzinfo=<UTC>), 'acc_count': 75, 'y_count': 162}
{'trunc_date': datetime.datetime(2020, 1, 22, 0, 0, tzinfo=<UTC>), 'acc_count': 162, 'y_count': 65}

Si scopre che l'operatore FirstValue richiede l'uso di una funzione di Windows in modo da non poter annidare FirtValue e quindi calcolare il ritardo, quindi in questo scenario non sono esattamente sicuro di poterlo fare. La domanda diventa come accedere alla colonna First_Value senza nidificare le finestre.