Wie schreibe ich, wie der Titel schon sagt, um die "existierende Klausel" in einem Django-Abfragesatz zu verwenden? Umfrage Notizen über.
Geben Sie beim Ausgeben einer Abfrage mit Django eine Bedingung als Parameter im Queryset-Objekt an.
models.py
from django.db import models
class Author(models.Model):
class Meta :
db_table = 'AUTHOR'
name = models.CharField('Autorenname', max_length=100)
birthday = models.DateField('Geburtstag')
class Book(models.Model):
class Meta :
db_table = 'BOOK'
name = models.CharField('Buchtitel', max_length=100)
price = models.IntegerField('Preis')
author = models.ForeignKey(Author, verbose_name='Autor')
Zum Beispiel für ein Modell wie ↑
Book.objects.filter(name__contains='Django', price__lte=3000)
Im Fall des Abfragesatzes von ↑ bedeutet dies, dass die Bedingungen "der Buchname enthält die Zeichenfolge 'Django'" und "der Preis beträgt 3000 oder weniger" angegeben sind und die tatsächlich ausgegebene Abfrage wie ↓ aussieht. werden.
SELECT ... FROM BOOK WHERE NAME LIKE '%Django%' AND PRICE <= 3000
Diese Bedingungen geben die Bedingungen direkt für die Felder im Buchmodell an. Wenn es sich jedoch um ein ForeignKey-Feld handelt, können Sie der Beziehung folgen und die Bedingungen für das Feld schreiben, auf das Sie sich beziehen möchten.
Book.objects.filter(author__name__contains='xxx')
Im Fall von ↑ wird die Spalte mit FK als Verknüpfungsbedingung verwendet, und die Abfrage ist wie in ↓ gezeigt.
SELECT ... FROM BOOK INNER JOIN AUTHOR ON (BOOK.AUTHOR_ID = AUTHOR.ID)
WHERE AUTHOR.NAME LIKE '%xxx%'
Beachten Sie, dass die Tabellenverknüpfung auf der Django-Seite automatisch generiert wird, indem die Beziehung aus dem FK-Feld verfolgt wird. Sie können die Tabellenverknüpfung nicht selbst durchführen, indem Sie das Feld ohne FK als Verknüpfungsbedingung verwenden.
Die EXISTS-Klausel in SQL wird in der Where-Klausel wie folgt verwendet.
SELECT ... FROM AUTHOR
WHERE EXISTS(
SELECT 1 FROM BOOK
WHERE BOOK.AUTHOR_ID = AUTHOR.ID
AND BOOK.PRICE >= 5000
)
In diesem Beispiel lautet SQL "Suche nach Autoren, die Bücher mit Preisen über 5000 veröffentlicht haben". Wenn Sie versuchen, dies in Djangos Abfragesatz auszudrücken, können Sie ihn über das zugehörige Feld als ↓ schreiben.
Author.objects.filter(book__price__gte=5000)
In diesem Fall werden jedoch "Autoren, die mehrere Bücher mit Preisen von 5000 oder mehr veröffentlicht haben", von der Anzahl der Bücher betroffen sein. Verwenden Sie die Methode "different", um Doppelarbeit zu vermeiden.
Author.objects.filter(book__price__gte=5000).distinct()
Das ist in Ordnung, aber Leistung ist verschwendet und vor allem nicht cool. Eine solche Bedingung "wenn ◯◯ existiert" ist klug, wenn Sie die existierende Klausel verwenden können ...
Nachdem wir verschiedene Dinge untersucht hatten, gab es eine Möglichkeit, die existierende Klausel richtig zu verwenden. (Aber nicht sehr klug)
Die zusätzliche Methode wurde in der offiziellen Django-Dokumentation erwähnt. Mit dieser Methode können Sie einige Ihrer Abfragen erweitern, z. B. select-, from- und where-Klauseln.
Dieses Mal fügen wir der where-Klausel eine Bedingung hinzu. Schreiben Sie also wie folgt
Author.objects.extra(where=['exists(select 1 from BOOK where BOOK.author_id=AUTHOR.id and BOOK.price >= 5000)'])
Die mit dem Inhalt von ↑ ausgegebene SQL ist wie in ↓ gezeigt.
SELECT "AUTHOR"."id", "AUTHOR"."name", "AUTHOR"."birthday" FROM "AUTHOR"
WHERE (exists(select 1 from BOOK where BOOK.author_id=AUTHOR.id and BOOK.price >= 5000))
Die durch extra angegebene Zeichenfolge wird hinzugefügt, da dies eine Bedingung für die where-Klausel ist. Darüber hinaus ist der durch extra hinzugefügte where-Parameter ein Listentyp. Wenn mehrere Bedingungen angegeben werden, wird er automatisch durch AND kombiniert.
Übrigens ist es auch möglich, die from-Klausel und die where-Klausel zusammen zu verwenden, um Tabellen ohne FK zu verbinden. Breites Anwendungsspektrum. Der Rückgabewert ist jedoch ein Queryset-Objekt, sodass Sie die Methodenkette unverändert verbinden können. Das ist praktisch.
Author.objects.extra(where=['exists(...Kürzung...)']).order_by('birthday')
↓ Es sieht so aus
SELECT "AUTHOR"."id", "AUTHOR"."name", "AUTHOR"."birthday" FROM "AUTHOR"
WHERE (exists(select 1 from BOOK where BOOK.author_id=AUTHOR.id and BOOK.price >= 5000))
ORDER BY "AUTHOR"."birthday" ASC
Dies ist ein Muster von allem. Solange Sie den Inhalt der Select-Klausel mit dem zu durchsuchenden Modellfeld abgleichen können, können Sie die gesamte SQL selbst schreiben.
Wenn dies die Bedingung des Beispiels ist, schreiben Sie als ↓.
>>> Author.objects.raw('''select id,name,birthday from AUTHOR
... where exists(
... select 1 from BOOK
... where BOOK.author_id=AUTHOR.id
... and BOOK.price >= 5000)''')
...
<RawQuerySet: 'select id,name,birthday from AUTHOR where exists(select 1 from BOOK where BOOK.author_id=AUTHOR.id and BOOK.price >= 5000)'>
Da die Rückgabe der raw-Methode ein RawQuerySet-Objekt ist, kann die Methodenkette von Queryset nicht verbunden werden. Nun, ich habe das gesamte SQL selbst geschrieben, sodass ich es nicht in die Methodenkette schreiben muss.
Benutzerdefiniertes SQL direkt ausführen
Dies ist ein Muster, das wirklich alles ist. Es ist nicht etwas, dass die existierende Klausel auf einer solchen Ebene verwendet wird, aber sie wird verwendet, wenn Sie DDL oder DML direkt ausgeben möchten. Oder geht es darum, eine Abfrage auszugeben, die keine entsprechende Modellklasse hat (z. B. Aufruf von VIEW oder FUNCTION)?
Wenn Sie es wagen, die Beispielabfrage auszuführen, können Sie wie ↓ schreiben
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute('select id,name,birthday from AUTHOR where exists(...Kürzung...)')
>>> cursor.fetchall()
[(1,'xxx',datetime.date(yyyy,mm,dd)), (2,'xxx',datetime.date(yyyy,mm,dd)),,,]
Das Ergebnis ist eine Liste von Tapples. Es ist kein Diktat, seien Sie also vorsichtig, wenn Sie mit dem Cursor abrufen.
Wenn Sie eine Abfrage schreiben möchten, die vom Django-Filter usw. nicht ausgedrückt werden kann, gibt es die folgenden drei Methoden.
Für das Thema dieser Zeit, "Write a exist Klausel", ist die zusätzliche Methode ausreichend. Wenn Sie eine komplexe Abfrage erstellen möchten, müssen Sie möglicherweise die Raw-Methode verwenden. Ich glaube nicht, dass es eine Chance gibt, das Cursorobjekt zum normalen Erstellen einer App zu verwenden. Dies kann beim Erstellen von APIs oder beim Entwickeln von Apps, die komplexe Datenflüsse generieren, ins Spiel kommen. (Ich habe es verwendet, als ich einen Befehl zum Generieren von Tabellenkommentaren in Django ausgeführt habe)
Vorerst gab es auch eine Möglichkeit, komplexes SQL auszuführen. Ja.
Recommended Posts