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 das ergebnis so sortiert haben, 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'
Die Ergebnisse wären 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, auch 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 die Bedingung fallen. Ich wollte die Testergebnisse nach fehlgeschlagenen Werten ordnen, Werte übergeben. So konnte ich zuerst die fehlerhaften Werte und dann die übergebenen Werte mit ORDER BY validieren.
Was ich nicht kann:
Nachdem ich diese Frage geschrieben habe, beginne ich zu denken, dass ich das überdenken muss, LOL!
...
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
Sie können einen LEFT JOIN mit "VALUES ('f', 1), ('p', 2), ('a', 3), ('i', 4)" verwenden und die zweite Spalte in Ihrer Bestellung 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.
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.
Verwenden Sie einen case
-Schalter, 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
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.
Die CASE
und ORDER BY
Vorschläge sollten alle funktionieren, aber ich werde ein Pferd mit einer anderen Farbe vorschlagen. Angenommen, es gibt nur eine vernünftige Anzahl von Werten für x_field
und Sie wissen bereits, was sie sind, erstellen Sie einen Aufzählungstyp mit den Werten F, P, A und I (zuzüglich aller anderen möglichen Werte). Die Aufzählungen werden in der Reihenfolge sortiert, die in der CREATE
-Anweisung angegeben ist. Sie können ausserdem aussagekräftige Wertnamen verwenden - Ihre eigentliche Anwendung hat dies wahrscheinlich getan, und Sie haben sie nur aus Gründen der Vertraulichkeit maskiert -, ohne unnötigen Speicherplatz zu verschwenden, da nur die Ordnungsposition gespeichert wird.
Sie können nach einer ausgewählten Spalte oder nach 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 "IsGen = 0" -Zeilen beginnt, gefolgt von "IsGen = 1" -Zeilen 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