Wir haben ein System in Django geschrieben, um Patienten für klinische Studien rekrutiert verfolgen. Tabellen werden verwendet, um die Anzahl der monatlich rekrutierten Patienten während eines Geschäftsjahres zu erfassen; Das Blatt enthält also nur 12 Monate Daten, obwohl eine Studie über Jahre laufen könnte.Wählen Sie die letzten Zeilen in Django ORM mit Gruppierung
Es gibt eine Tabelle in einer Django-Datenbank, in die die Tabellenblätter jeden Monat importiert werden. Die Daten umfassen den Monat/das Jahr, eine Anzahl von Patienten und einige andere Felder. Jeder Import enthält alle Daten der Vormonate; Damit müssen Sie sicherstellen, dass auf dem Importblatt seit dem letzten Import keine Daten geändert wurden.
Zum Beispiel kann die Importtabelle mit zwei Einfuhren (die ersten bis Januar und die zweiten bis Februar) würde wie folgt aussehen:
id | study_id | data_date | patient_count | [other fields] -->
100 5456 2016-04-01 10 ...
101 5456 2016-05-01 8 ...
102 5456 2016-06-01 5 ...
... all months in between ...
109 5456 2016-01-01 12 ...
110 5456 2016-02-01 NULL ...
111 5456 2016-03-01 NULL ...
112 5456 2016-04-01 10 ...
113 5456 2016-05-01 8 ...
114 5456 2016-06-01 5 ...
... all months in between ...
121 5456 2016-01-01 12 ...
122 5456 2016-02-01 6 ...
123 5456 2016-03-01 NULL ...
Die anderen Felder enthalten einen Fremdschlüssel zu einer anderen Tabelle der umschließende tatsächliche Studienidentifikationsnummer (iras_number
), also muss ich mich damit verbinden, um die Zeilen für eine bestimmte Studie auszuwählen.
Ich möchte die letzten Werte von data_date
und patient_count
für eine Studie, die mehr als ein Haushaltsjahr erstrecken kann, so habe ich versucht, diese Abfrage (iras_number
wird an die Funktion übergeben diese Abfrage durchführen):
totals = ImportStudyData.objects.values('data_date', 'patient_count') \
.filter(import_study__iras_number=iras_number) \
.annotate(max_id=Max('id')).order_by()
jedoch erzeugt dies eine SQL-Abfrage, die patient_count
im GROUP BY
enthält, in doppelten Zeilen resultierenden:
data_date | patient_count | max_id
2016-04-01 10 100
2016-04-01 10 112
2016-05-01 8 101
2016-05-01 8 113
...
2016-01-01 12 109
2016-01-01 12 121
2016-02-01 NULL 110
2016-02-01 6 122
Wie wähle ich die neuesten data_date
und patient_count
aus der Tabelle mit dem ORM?
Wenn ich die SQL geschrieben haben würde ich eine innere Auswahl der max(id)
von data_date
gruppierte tun und dass dann beitreten verwenden oder eine IN
Abfrage verwenden, die Felder I aus der Tabelle benötigen auszuwählen; als solche:
SELECT data_date, patient_count
FROM importstudydata
WHERE id IN (
SELECT MAX(id) AS "max_id"
FROM importstudydata INNER JOIN importstudy
ON importstudydata.import_study_id = importstudy.id
WHERE importstudy.iras_number = 5456
GROUP BY importstudydata.data_date
)
ORDER BY data_date ASC
Ich habe versucht, ein inneres wählen Sie erstellen, um die SQL-Abfrage zu replizieren, aber die innere Auswahl kehrt mehr als ein Feld (Spalte) a bewirkt, dass die Abfrage fehlschlagen:
totals = ImportStudyData.objects.values('data_date', 'patient_count') \
.filter(id__in=ImportStudyData.objects.values('data_date') \
.filter(import_study__iras_number=iras_number) \
.annotate(max_data_id=Max('id'))
Nun kann ich die innere Auswahl nicht erhalten, nur die max(id)
gruppiert von `data_date 'zurückzugeben und es in einer einzigen SQL-Abfrage durchgeführt werden.
Wenn ich 'distinct = True' im Annotate-Aufruf hinzufüge, bekomme ich den Fehler '' bool 'object hat kein Attribut' resolve_expression''. Muss der 'distinct' Parameter Teil der' max' Funktionsparameter sein? – Tony
Das Verschieben von "distinct" an das Ende des Abfrage-Strings bedeutet, dass es zur Ausführung der SQL-Anweisung führt, aber es gibt immer noch Duplikate zurück, da "distinct" auf alle Felder angewendet wird ('data_date',' patient_count' und 'max_id')) die bereits verschieden sind. – Tony