PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

ActiveRecord:Wie finde ich Eltern, deren ALLE Kinder eine Bedingung erfüllen?

Mit arel kann dich ziemlich weit bringen. Der knifflige Teil ist, wie Sie nicht Ihre gesamte Abfrage mit arel schreiben 's eigene Abfragesyntax?

Hier ist ein Trick:Wenn Sie Ihre Abfrage mit where erstellen , wenn Sie arel verwenden Bedingungen erhalten Sie einige zusätzliche Methoden kostenlos. Beispielsweise können Sie die Unterabfrage, die Sie dort haben, mit .exists.not abschließen , wodurch Sie einen (NOT ( EXISTS (subquery))) erhalten Werfen Sie das in das where der Eltern -Klausel und fertig.

Die Frage ist, wie verweisen Sie auf die beteiligten Tabellen? Dafür brauchst du Arel. Sie könnten Verwenden Sie Arels where mit seinen hässlichen Bedingungen wie a.eq b . Aber wieso? Da es sich um eine Gleichheitsbedingung handelt, können Sie stattdessen die Bedingungen von Rails verwenden! Sie können auf die abgefragte Tabelle mit einem Hash-Schlüssel verweisen, aber für die andere Tabelle (in der äußeren Abfrage) können Sie deren arel_table verwenden . Sehen Sie sich das an:

parents = Parent.arel_table
Parent.where(
  Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)

Sie können die Nutzung von Arel sogar reduzieren, indem Sie ein wenig auf Strings zurückgreifen und sich darauf verlassen, dass Sie Unterabfragen als Parameter in Rails' where einspeisen können . Es hat nicht viel Nutzen, aber es zwingt Sie nicht, sich zu sehr mit Arels Methoden zu beschäftigen, also können Sie diesen Trick oder andere SQL-Operatoren verwenden, die eine Unterabfrage verwenden (gibt es überhaupt andere?):

parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
  Child.where(parent_id: parents[:id], other_parent_id: nil)
)

Die zwei Hauptpunkte hier sind:

  • Sie können Unterabfragen genauso erstellen, wie Sie es gewohnt sind, reguläre Abfragen zu erstellen, indem Sie mit Arel auf die Tabelle der äußeren Abfrage verweisen. Es kann nicht einmal ein echter Tisch sein, es kann ein Alias ​​sein! Verrücktes Zeug.
  • Sie können Unterabfragen als Parameter für where von Rails verwenden Methode ganz gut.