Ok j'ai une table avec une clé indexée et un champ non indexé. Je dois trouver tous les enregistrements avec une certaine valeur et renvoyer la ligne. Je voudrais savoir si je peux commander par plusieurs valeurs.
Exemple:
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: voudrait que les résultats soient ordonnés comme ceci, 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'
Donc, les résultats seraient:
id x_field
-- -----
127 f
133 p
134 p
135 i
123 a
124 a
125 a
129 a
La syntaxe est valide, mais lorsque j'exécute la requête, elle ne renvoie aucun résultat, même si je la limite à 1 enregistrement. Y a-t-il une autre façon de s'y prendre?
Pensez à x_field en tant que résultats de test et je dois valider tous les enregistrements qui tombent dans cette condition. Je voulais classer les résultats des tests par valeurs échouées, valeurs transmises. Je pouvais donc d'abord valider les valeurs ayant échoué, puis les valeurs transmises à l'aide de ORDER BY.
Ce que je ne peux pas faire:
Après avoir écrit cette question, je commence à penser que je dois repenser cela, 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
Vous pouvez utiliser un LEFT JOIN avec "VALUES ('f', 1), ('p', 2), ('a', 3), ('i', 4)" et utiliser la deuxième colonne de votre commande. -par expression. Postgres utilisera une jointure de hachage qui sera beaucoup plus rapide qu'un énorme cas si vous avez beaucoup de valeurs. Et il est plus facile de se générer automatiquement.
Si cette information de commande est fixe, alors il devrait avoir sa propre table.
Essayer:
ORDER BY x_field='F', x_field='P', x_field='A', x_field='I'
Vous étiez sur la bonne voie, mais en mettant x_field uniquement sur la valeur F, les 3 autres ont été traités comme des constantes et ne sont comparés à aucun élément de l'ensemble de données.
Utilisez un commutateur case
pour traduire les codes en nombres pouvant être triés:
ORDER BY
case x_field
when 'f' then 1
when 'p' then 2
when 'i' then 3
when 'a' then 4
else 5
end
J'ai trouvé une solution beaucoup plus propre pour cela:
ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)
Remarque: array_position nécessite Postgres version 9.5 ou supérieure.
Les CASE
et ORDER BY
_ les suggestions devraient toutes marcher, mais je vais suggérer un cheval de couleur différente. En supposant qu'il n'y ait qu'un nombre raisonnable de valeurs pour x_field
et vous savez déjà ce qu’ils sont, créez un type énuméré avec F, P, A et I comme valeurs (plus les autres valeurs possibles s’appliquant). Les énumérations trieront dans l'ordre implicite de leur instruction CREATE
. En outre, vous pouvez utiliser des noms de valeur méchants (votre application réelle le fait probablement et vous les avez masqués pour des raisons de confidentialité) sans gaspiller d'espace, car seule la position ordinale est stockée.
Vous pouvez commander par une colonne sélectionnée ou d'autres expressions.
Voici un exemple, comment commander par le résultat d'une instruction case:
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
Le résultat sera une liste commençant par "IsGen = 0", suivie de "IsGen = 1" et de toutes les autres lignes à la fin.
Vous pouvez ajouter plus de paramètres d'ordre à la fin:
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