2010-02-12 12 views
5

Diese Frage hat eine kleine Geschichte — Is there a way to make a query respect the order of the inputted parameters?Machen PostgreSQL die Reihenfolge der eingegebenen Parameter?

Ich bin neu zu „spezialisiert“ Abfragen erstellen, so dass ich davon ausgegangen, dass, wenn ich eine IN Klausel als Teil einer SELECT Abfrage liefern, wird es Ergebnisse in der gleichen Rück Auftrag. Leider ist das nicht der Fall.

SELECT * FROM artists WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37) 
>>> [7, 32, 3, 8, 4, 2, 31, 9, 37, 13, 16, 1, 5, 15, 14] 

(Haben Sie nicht den Schritt umfassen, wo ich Python eine Schleife durch das Ergebnis verwendet und die IDs zu einer Liste anhängen.)

Die Frage ist also, ist es eine Möglichkeit, Postgres zu machen, den Respekt Bestellung der Parameter in einem IN Klausel durch Rückgabe der Ergebnisse die gleiche Auftrag gegeben?

Antwort

5

Abfrageergebnisse werden in nichtdeterministischer Reihenfolge zurückgegeben, sofern Sie keine ORDER BY-Klausel angeben.

Wenn Sie die Abfrage wirklich so ausführen möchten, wie Sie es wünschen, können Sie eine solche Klausel konstruieren. Hier ist ein Beispiel, das einen Teil Ihrer Daten verwendet.

create table artists (
id integer not null primary key, 
name char(1) not null); 

insert into artists 
values 
    (8, 'a'), 
    (1, 'b'), 
    (2, 'c'), 
    (15, 'd'), 
    (14, 'e'), 
    (3, 'f'), 
    (13, 'g'); 

select * 
from artists 
where id in (8, 1, 2, 15, 14, 3, 13) 
order by 
    id = 8 desc, 
    id = 1 desc, 
    id = 2 desc, 
    id = 15 desc, 
    id = 14 desc, 
    id = 3 desc, 
    id = 13 desc; 

Auf dieser Grundlage und auf Ihre andere Frage, ich denke, es ist etwas falsch mit Ihrem Modell oder die Art und Weise Sie dies zu tun versuchen. Vielleicht solltest du eine allgemeinere Frage stellen, wie du das machen sollst, was du zu tun versuchst.

Wenn Sie Künstler und Ranking-Tabellen haben, sollten Sie in der Lage sein, etwas zu tun (oder das Äquivalent durch Ihre ORM).

select 
    a.* 
from 
    artists a, 
    rankings r 
where 
    a.id = r.artist_id 
order by 
    r.score desc; 
+0

Vielen Dank für Ihre Antwort. Ich habe eine Menge darüber offen gelassen, wie meine Bewerbung funktioniert. Kurz gesagt, ein Ranking entspricht nicht nur einem Künstler, sondern kann einer beliebigen Anzahl von Objekttypen entsprechen, die wir ihm geben. Das heißt, ich verwende Djangos Generika, um diese Beziehungen zu erstellen, was es etwas schwieriger macht, das zu tun, was ich hier versuche. –

+0

Sehr traurig, dass Postgres die Bestellung nicht erhalten kann. Das würde mich auch vor vielen Problemen bewahren! Ich bin in einer ähnlichen Situation und die Sortierreihenfolge ändert sich mehrmals pro Minute, also mache ich die Bestellung in meiner App, um völlig unnötige Datenbankschreibvorgänge zu verhindern. Also Bestellung ist keine Option, – Malte

2

Ich schlage vor, Sie lassen PostGreSQL den Satz in beliebiger Reihenfolge zurückkehren (vor allem, da es schwierig ist, feinkörnige SQL-Level-Steuerung von einer Django-Schnittstelle zu tun), dann sortiert sich in der Art und Weise wollen Sie in Python - theresultset.sort(key=yourlistofids.index) sollte gut gehen (wenn theresultset ist die Liste der willkürlichen Reihenfolge aus der Datenbank und yourlistofids ist die Liste, deren Reihenfolge Sie beibehalten möchten).

+0

Eine andere Situation, in der ich wünschte, ich könnte beide Antworten akzeptieren. :) Vielen Dank, ich werde persönlich diesen Weg gehen, aber für das Interesse der Leute, die diese Frage von Google finden, werde ich die Antwort von cope akzeptieren. –

+0

FWIW, empfehle ich gegen diese Lösung. Die Datenbank ist für die Sortierung ausgelegt, die App-Sprache dagegen nicht. Es wird viel langsamer sein, als die Datenbank sortieren zu lassen. – theory

+0

@Theory, Python ist ** hervorragend ** beim Sortieren (Daten, die in den Speicher passt) - seine 'timsort' Algorithmus ist so großartig, es hat auch viel Aufmerksamkeit z. in der Java-Welt. Es ist absurd von dir zu behaupten, dass "Python" nicht "zum Sortieren" gedacht ist, wenn es so * großartig * darin ist. –

0

Ein anderer Weg:

SELECT * 
FROM artists 
WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37) 
ORDER BY POSITION(id::text in '(8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37)'); 
+0

Die Positionsfunktion bestimmt die Position einer Zeichenfolge in einer anderen Zeichenfolge. Dies funktioniert nicht richtig, weil nicht alle Ids die gleiche Anzahl von Ziffern haben. Angenommen, Sie wollten, dass ID 14 zuerst ist. Sie könnten damit enden, dass ID 1 zuerst ist. Oder ID 4. –

Verwandte Themen