SQL ORDER BY mehrere Werte in einer bestimmten Reihenfolge?


94

Ok, ich habe eine Tabelle mit einem indizierten Schlüssel und einem nicht indizierten Feld. Ich muss alle Datensätze mit einem bestimmten Wert finden und die Zeile zurückgeben. Ich würde gerne wissen, ob ich nach mehreren Werten bestellen kann.

Beispiel:

id     x_field
--     -----
123    a
124    a
125    a
126    b
127    f
128    b
129    a
130    x
131    x
132    b
133    p
134    p
135    i

pseudo: möchte, dass die Ergebnisse so geordnet werden, where ORDER BY x_field = 'f', 'p', 'i', 'a'

SELECT *
FROM table
WHERE id NOT IN (126)
ORDER BY x_field 'f', 'p', 'i', 'a'

Das Ergebnis wäre also:

id     x_field
--     -----
127    f
133    p
134    p
135    i
123    a
124    a
125    a
129    a

Die Syntax ist gültig, aber wenn ich die Abfrage ausführe, werden keine Ergebnisse zurückgegeben, selbst wenn ich sie auf 1 Datensatz beschränke. Gibt es einen anderen Weg, dies zu tun?

Stellen Sie sich das x_field als Testergebnis vor und ich muss alle Datensätze validieren, die in den Zustand fallen. Ich wollte die Testergebnisse nach fehlgeschlagenen Werten und übergebenen Werten ordnen. So konnte ich zuerst die fehlgeschlagenen Werte und dann die übergebenen Werte mit ORDER BY validieren.

Was ich nicht kann:

  • GROUP BY, da ich die spezifischen Datensatzwerte zurückgeben muss
  • WO x_field IN ('f', 'p', 'i', 'a'), ich benötige alle Werte, da ich versuche, eine Abfrage für mehrere Validierungstests zu verwenden. Und x_field-Werte sind nicht in DESC / ASC-Reihenfolge

Nachdem ich diese Frage geschrieben habe, denke ich, dass ich das überdenken muss, LOL!


Vielleicht stattdessen eine Gewerkschaft? Erstellen Sie separate Abfragen in der Reihenfolge, in der die Ergebnisse zurückgegeben werden sollen, und führen Sie dann eine Vereinigung dieser Abfragen durch.
Kinakuta

Antworten:


178
...
WHERE
   x_field IN ('f', 'p', 'i', 'a') ...
ORDER BY
   CASE x_field
      WHEN 'f' THEN 1
      WHEN 'p' THEN 2
      WHEN 'i' THEN 3
      WHEN 'a' THEN 4
      ELSE 5 --needed only is no IN clause above. eg when = 'b'
   END, id

28

Sie können einen LEFT JOIN mit "VALUES ('f', 1), ('p', 2), ('a', 3), ('i', 4)" verwenden und die zweite Spalte in Ihrer Reihenfolge verwenden -durch Ausdruck. Postgres verwendet einen Hash-Join, der viel schneller ist als ein riesiger CASE, wenn Sie viele Werte haben. Und es ist einfacher, automatisch zu generieren.

Wenn diese Bestellinformationen festgelegt sind, sollte sie eine eigene Tabelle haben.


6
Dies ist bei weitem die eleganteste Lösung!
jnns

26

Versuchen:

ORDER BY x_field='F', x_field='P', x_field='A', x_field='I'

Sie waren auf dem richtigen Weg, aber indem Sie x_field nur auf den F-Wert setzen, wurden die anderen 3 als Konstanten behandelt und nicht mit irgendetwas im Datensatz verglichen.


Unterstützt Postgres implizite Boolesche Werte? Wenn ja, wie sortiert Boolesch?
Gbn

Ich mochte diese Lösung, aber sie gab nichts mehr zurück.
Phill Pafford

@gbn, Ja und falsch <wahr. Ich hätte erwartet, dass das funktioniert.
Andrew Lazarus

6
Ja, es funktioniert Ereignis in Postgres. Hinweis zu dieser Lösung ist, dass Sie das Ergebnis in umgekehrter Reihenfolge sortieren. Sie müssen also die Felder in umgekehrter Reihenfolge platzieren: ORDER BY x_field = 'A', x_field = 'I', x_field = 'P', x_field = 'F',
igo

16

Verwenden Sie einen caseSchalter, um die Codes in Zahlen zu übersetzen, die sortiert werden können:

ORDER BY
  case x_field
  when 'f' then 1
  when 'p' then 2
  when 'i' then 3
  when 'a' then 4
  else 5
  end

10

Ich habe dafür eine viel sauberere Lösung gefunden:

ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)

Hinweis: array_position benötigt Postgres v9.5 oder höher.


1
Es ist wichtig zu beachten, dass array_position () nur in Postgres v9.5 ab afaik verfügbar ist.
Bigsee

Vielen Dank, viel lieber als die CASE-Methoden. Funktioniert auch mit ganzen Zahlen; array_position(ARRAY[1, 0]::integer[], x_field)
Paul Watson

7

Die CASEund ORDER BYVorschläge sollten alle funktionieren, aber ich werde ein Pferd einer anderen Farbe vorschlagen. Angenommen, es gibt nur eine angemessene Anzahl von Werten für x_fieldund Sie wissen bereits, um welche es sich handelt, erstellen Sie einen Aufzählungstyp mit F, P, A und I als Werten (zuzüglich aller anderen möglichen Werte). Aufzählungen werden in der Reihenfolge sortiert, in der sie angegeben sind CREATE. Sie können auch aussagekräftige Wertnamen verwenden - Ihre reale Anwendung tut dies wahrscheinlich und Sie haben sie nur aus Gründen der Vertraulichkeit maskiert -, ohne Speicherplatz zu verschwenden, da nur die Ordnungsposition gespeichert wird.


1

Sie können nach einer ausgewählten Spalte oder anderen Ausdrücken sortieren.

Hier ein Beispiel, wie man nach dem Ergebnis einer case-Anweisung ordnet:

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END

Das Ergebnis ist eine Liste, die mit den Zeilen "IsGen = 0" beginnt, gefolgt von den Zeilen "IsGen = 1" und allen anderen Zeilen am Ende.

Sie können am Ende weitere Bestellparameter hinzufügen:

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END,
         col1,
         col2

Dieses Code-Snippet kann das Problem zwar lösen, erklärt jedoch nicht, warum oder wie es die Frage beantwortet. Bitte geben Sie eine Erklärung für Ihren Code an , da dies wirklich zur Verbesserung der Qualität Ihres Beitrags beiträgt. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Samuel Philipp

0

Für jemanden, der neu bei ORDER BY with CASE ist, kann dies nützlich sein

ORDER BY 
    CASE WHEN GRADE = 'A' THEN 0
         WHEN GRADE = 'B' THEN 1
         ELSE 2 END

-2

Sie können die Position (Text in Text) verwenden, um die Reihenfolge zu bestimmen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.