web-dev-qa-db-fra.com

sql ORDER BY plusieurs valeurs dans un ordre spécifique?

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:

  • GROUP BY, car je dois renvoyer les valeurs d'enregistrement spécifiques
  • WHERE x_field IN ('f', 'p', 'i', 'a'), j'ai besoin de toutes les valeurs car j'essaie d'utiliser une requête pour plusieurs tests de validation. Et les valeurs de x_field ne sont pas dans l'ordre DESC/ASC

Après avoir écrit cette question, je commence à penser que je dois repenser cela, LOL!

74
Phill Pafford
...
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
147
gbn

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.

24
peufeu

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.

19
Marc B

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
12
Guffa

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.

6
rept

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.

6
Andrew Lazarus

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
0
JIYAUL MUSTAPHA