Angenommen, wir haben ein Modell in Django, das wie folgt definiert ist:
class Literal:
name = models.CharField(...)
...
Das Namensfeld ist nicht eindeutig und kann daher doppelte Werte haben. Ich muss die folgende Aufgabe ausführen: Wählen Sie alle Zeilen aus dem Modell aus, die mindestens einen doppelten Wert des name
Felds haben.
Ich weiß, wie man es mit einfachem SQL macht (möglicherweise nicht die beste Lösung):
select * from literal where name IN (
select name from literal group by name having count((name)) > 1
);
Ist es also möglich, dies mit Django ORM auszuwählen? Oder bessere SQL-Lösung?
sql
django
django-orm
Dragoner
quelle
quelle
Literal.objects.values('name').annotate(name_count=Count('name')).filter(name_count__gt=1)
?Cannot resolve keyword 'id_count' into field
values_list('name', flat=True)
Count
Anmerkung angeben, unter der gespeichert werden soll, wird standardmäßig der Fehler verwendet[field]__count
. Mit dieser Syntax mit doppeltem Unterstrich interpretiert Django jedoch auch, dass Sie einen Join durchführen möchten. Wenn Sie also versuchen, danach zu filtern, denkt Django, dass Sie versuchen, eine Verknüpfung herzustellen, mitcount
der es offensichtlich keine gibt. Die Korrektur besteht darin, einen Namen für Ihr Anmerkungsergebnis anzugeben, dh stattdessen zuannotate(mycount=Count('id'))
filternmycount
.values('name')
nach Ihrem Aufruf zum Kommentieren einen weiteren Aufruf hinzufügen , können Sie das Listenverständnis entfernen und angeben,Literal.objects.filter(name__in=dupes)
wodurch dies alles in einer einzigen Abfrage ausgeführt werden kann.Dies wurde als Bearbeitung abgelehnt. Also hier ist es als bessere Antwort
Dies gibt ein
ValuesQuerySet
mit allen doppelten Namen zurück. Sie können dies dann jedoch verwenden, um eine reguläreQuerySet
Abfrage zu erstellen, indem Sie sie in eine andere Abfrage zurückführen. Das Django-ORM ist intelligent genug, um diese in einer einzigen Abfrage zu kombinieren:Der zusätzliche Anruf
.values('name')
nach dem Annotate-Aufruf sieht etwas seltsam aus. Ohne dies schlägt die Unterabfrage fehl. Die zusätzlichen Werte bringen das ORM dazu, nur die Namensspalte für die Unterabfrage auszuwählen.quelle
.order_by()
?GROUP BY
Klausel, und das bricht die Dinge. Fand das heraus, als du mit Subquery spielst (in dem du über eine sehr ähnliche Gruppierung machst.values()
)Versuchen Sie es mit Aggregation
quelle
Wenn Sie PostgreSQL verwenden, können Sie Folgendes tun:
Dies führt zu dieser ziemlich einfachen SQL-Abfrage:
quelle
Wenn Sie nur eine Namensliste, aber keine Objekte erstellen möchten, können Sie die folgende Abfrage verwenden
quelle