Ich möchte diese Abfrage ausführen:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Aber ich bekomme diesen Fehler:
PG :: Fehler: FEHLER: SELECT DISTINCT ON-Ausdrücke müssen mit den anfänglichen ORDER BY-Ausdrücken übereinstimmen
Durch Hinzufügen address_id
als ersten ORDER BY
Ausdruck wird der Fehler stummgeschaltet, aber ich möchte wirklich keine Sortierung hinzufügen address_id
. Kann man ohne Bestellung auskommen address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
quelle
quelle
Antworten:
Die Dokumentation sagt:
Offizielle Dokumentation
Sie müssen also
address_id
die Bestellung bis hinzufügen .Wenn Sie alternativ nach der vollständigen Zeile suchen, die für jedes Produkt das zuletzt gekaufte Produkt enthält
address_id
und deren Ergebnis nach sortiertpurchased_at
ist, versuchen Sie alternativ, ein Problem mit dem größten N pro Gruppe zu lösen, das mit den folgenden Ansätzen gelöst werden kann:Die allgemeine Lösung, die in den meisten DBMS funktionieren sollte:
Eine PostgreSQL-orientierte Lösung basierend auf der Antwort von @ hkf:
Problem hier geklärt, erweitert und gelöst: Auswahl von Zeilen, die nach einer Spalte geordnet und in einer anderen getrennt sind
quelle
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. Zwei Datensätze mit derselben Adresse_ID, aber unterschiedlichen Werten für gekaufte_at führen jedoch zu Duplikaten im zurückgegebenen Satz. Stellen Sie sicher, dass Sie die Daten kennen, die Sie abfragen.Sie können nach address_id in einer Unterabfrage und dann nach Ihren Wünschen in einer äußeren Abfrage bestellen.
quelle
select
, glaube ich nicht, dass dies Produktionscode ist?address_id
zweimal (ohne Notwendigkeit) zurückkehren. Viele Clients haben Probleme mit doppelten Spaltennamen.ORDER BY address_id DESC
ist sinnlos und irreführend. In dieser Abfrage ist nichts nützlich. Das Ergebnis ist eine willkürliche Auswahl aus jedem Satz von Zeilen mit derselbenaddress_id
, nicht aus der Zeile mit der neuestenpurchased_at
. Die zweideutige Frage hat dies nicht explizit gefordert, aber das ist mit ziemlicher Sicherheit die Absicht des OP. Kurz gesagt: Verwenden Sie diese Abfrage nicht . Ich habe Alternativen mit Erklärung gepostet.Eine Unterabfrage kann es lösen:
Führende Ausdrücke in
ORDER BY
müssen mit Spalten in übereinstimmenDISTINCT ON
, damit Sie nicht nach verschiedenen Spalten in derselben sortieren könnenSELECT
.Verwenden Sie eine zusätzliche
ORDER BY
Zeile in der Unterabfrage nur, wenn Sie aus jedem Satz eine bestimmte Zeile auswählen möchten:Wenn
purchased_at
möglichNULL
, überlegen SieDESC NULLS LAST
. Stellen Sie jedoch sicher, dass Ihr Index übereinstimmt, wenn Sie ihn verwenden möchten. Sehen:Verwandte, mit mehr Erklärung:
quelle
DISTINCT ON
ohne Matching verwendenORDER BY
. Die erste Abfrage erfordert eineORDER BY address_id
interne Abfrage .DISTINCT ON
ohneORDER BY
in der gleichen Abfrage verwenden. Sie erhalten eine willkürliche Zeile von jeder Gruppe von Peers, dieDISTINCT ON
in diesem Fall durch die Klausel definiert sind . Probieren Sie es aus oder folgen Sie den obigen Links für Details und Links zum Handbuch.ORDER BY
in der gleichen Abfrage (die gleicheSELECT
) kann einfach nicht widersprechenDISTINCT ON
. Das habe ich auch erklärt.ORDER BY
Hinweises „Unvorhersehbar, wenn nicht verwendet wird“ in den Dokumenten, da es für mich keinen Sinn macht, dass die Funktion implementiert ist, um mit nicht aufeinanderfolgenden Wertesätzen umgehen zu können Nutzen Sie das mit einer expliziten Bestellung. Nervig.DISTINCT ON
(noch) nicht nach Ausdrücken sortiert .Die Fensterfunktion kann das in einem Durchgang lösen:
quelle
address_id
. Das Prinzip könnte jedoch funktionieren. Verwandte Beispiele: stackoverflow.com/a/22064571/939860 oder stackoverflow.com/a/11533808/939860 . Es gibt jedoch kürzere und / oder schnellere Abfragen für das vorliegende Problem.Für alle, die Flask-SQLAlchemy verwenden, hat dies bei mir funktioniert
quelle
query.distinct(foo).from_self().order(bar)
Purchases.query
?Sie können dies auch tun, indem Sie die group by-Klausel verwenden
quelle
purchases
nur die beiden Spaltenaddress_id
undpurchased_at
). Aus diesem GrundGROUP BY
müssen Sie eine Aggregatfunktion verwenden, um den Wert jeder Spalte zu ermitteln, die nicht für die Gruppierung verwendet wird. Daher stammen alle Werte aus verschiedenen Zeilen der Gruppe, es sei denn, Sie führen hässliche und ineffiziente Gymnastik durch. Dies kann nur mithilfe von Fensterfunktionen und nicht mithilfe von Fensterfunktionen behoben werdenGROUP BY
.