Ich frage mich, ob es einen Weg gibt (möglicherweise einen besseren Weg), nach der Reihenfolge der Werte in einer IN () -Klausel zu ordnen.
Das Problem ist, dass ich zwei Abfragen habe, eine, die alle IDs erhält, und die zweite, die alle Informationen abruft. Der erste erstellt die Reihenfolge der IDs, nach denen der zweite bestellen soll. Die IDs werden in der richtigen Reihenfolge in eine IN () - Klausel eingefügt.
Es wäre also so etwas wie (extrem vereinfacht):
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
Das Problem ist, dass die zweite Abfrage die Ergebnisse nicht in derselben Reihenfolge zurückgibt, in der die IDs in die IN () - Klausel eingefügt wurden.
Eine Lösung, die ich gefunden habe, besteht darin, alle IDs in eine temporäre Tabelle mit einem automatisch inkrementierenden Feld einzufügen, das dann in die zweite Abfrage eingefügt wird.
Gibt es eine bessere Option?
Hinweis: Da die erste Abfrage "vom Benutzer" und die zweite in einem Hintergrundprozess ausgeführt wird, gibt es keine Möglichkeit, die 2-in-1-Abfrage mithilfe von Unterabfragen zu kombinieren.
Ich verwende MySQL, aber ich denke, es könnte nützlich sein, zu notieren, welche Optionen es auch für andere DBs gibt.
quelle
IN
undFIELD
Parameter gleich sind. Dies in einem Programmcode zu tun, kann durch Verwendung dieses zusätzlichen Wissens schneller sein. Natürlich könnte es klüger sein, diese Belastung eher auf den Client als auf den Server zu übertragen, wenn Sie die Serverleistung im Auge behalten.sqlite
?Im Folgenden erfahren Sie, wie Sie sortierte Daten erhalten.
quelle
Zwei Lösungen, die mir in den Sinn kommen:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
(
instr()
ist von Oracle; vielleicht haben Sielocate()
odercharindex()
oder so etwas)quelle
Ans, um sortierte Daten zu erhalten.
quelle
Wenn Sie eine Abfrage willkürlich nach Werten sortieren möchten, die von der Abfrage in MS SQL Server 2008+ eingegeben wurden , können Sie eine Tabelle im laufenden Betrieb erstellen und einen Join wie diesen ausführen (unter Verwendung der Nomenklatur aus OP).
Wenn Sie die VALUES-Anweisung durch etwas anderes ersetzen, das dasselbe tut, jedoch in ANSI SQL, sollte dies in jeder SQL-Datenbank funktionieren.
Hinweis: Die zweite Spalte in der erstellten Tabelle (orderTbl.orderIdx) ist erforderlich, wenn Datensatzgruppen abgefragt werden, die größer als 100 sind. Ich hatte ursprünglich keine orderIdx-Spalte, stellte jedoch fest, dass ich bei Ergebnismengen größer als 100 explizit nach dieser Spalte sortieren musste. in SQL Server Express 2014 sowieso.
quelle
orderTbl.orderKey
,orderTbl.orderIndex
durchorderKey
,orderIndex
hat wirklich super funktioniert
quelle
Die IN-Klausel beschreibt eine Reihe von Werten, und Mengen haben keine Reihenfolge.
Ihre Lösung mit einem Join und einer anschließenden Bestellung in der
display_order
Spalte ist die nahezu korrekte Lösung. Alles andere ist wahrscheinlich ein DBMS-spezifischer Hack (oder macht einige Dinge mit den OLAP-Funktionen in Standard-SQL). Sicherlich ist der Join die nahezu portable Lösung (obwohl das Generieren der Daten mit dendisplay_order
Werten problematisch sein kann). Beachten Sie, dass Sie möglicherweise die Bestellspalten auswählen müssen. Das war früher eine Anforderung in Standard-SQL, obwohl ich glaube, dass es vor einiger Zeit (vielleicht schon vor SQL-92) in der Regel gelockert wurde.quelle
Für Oracle funktioniert Johns Lösung mit der Funktion instr (). Hier ist eine etwas andere Lösung, die funktioniert hat -
SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)
quelle
Verwenden Sie die MySQL- Funktion FIND_IN_SET :
quelle
Ich habe gerade versucht, dies zu tun, ist MS SQL Server, wo wir kein FIELD () haben:
Beachten Sie, dass ich auch Duplikate zulasse.
quelle
Mein erster Gedanke war, eine einzelne Abfrage zu schreiben, aber Sie sagten, dies sei nicht möglich, da eine vom Benutzer und die andere im Hintergrund ausgeführt wird. Wie speichern Sie die Liste der IDs, die vom Benutzer an den Hintergrundprozess übergeben werden sollen? Warum legen Sie sie nicht in eine temporäre Tabelle mit einer Spalte, um die Reihenfolge zu kennzeichnen?
Wie wäre es damit:
quelle
Ich denke, Sie sollten es schaffen, Ihre Daten so zu speichern, dass Sie einfach einen Join durchführen und es perfekt ist, damit keine Hacks und komplizierten Dinge passieren.
Ich habe zum Beispiel eine "Kürzlich gespielte" Liste von Track-IDs, auf SQLite mache ich einfach:
quelle
Probieren Sie es aus:
Die WHEREs werden wahrscheinlich ein wenig angepasst, damit die korrelierten Unterabfragen ordnungsgemäß funktionieren, aber das Grundprinzip sollte solide sein.
quelle