web-dev-qa-db-fra.com

Commande personnalisée par explication

Je l'ai trouvé il y a quelque temps et je l'utilise depuis; cependant, en y regardant aujourd'hui, j'ai réalisé que je ne comprends pas bien pourquoi cela fonctionne. Est-ce que quelqu'un peut l'éclairer pour moi?

ORDER BY  s.type!= 'Nails',
          s.type!= 'Bolts',
          s.type!= 'Washers',
          s.type!= 'Screws',
          s.type!= 'Staples',
          s.type!= 'Nuts', ...

Si je commande par type, il trie par ordre alphabétique. Si j'utilise l'exemple ci-dessus, il utilise le même ordre que les positions de ligne. Ce que je ne comprends pas, c'est l'utilisation de! =. Si j'utilise = il apparaît dans l'ordre inverse. Je ne peux pas comprendre ce concept.

Cela me ferait penser que l'utilisation de = à la place des! = Ci-dessus placerait Nails en premier, mais ce n'est pas le cas, il le place en dernier. Je suppose que ma question est la suivante: pourquoi dois-je utiliser! =, Pas = dans cette situation?

57
Evil Elf

Je ne l'ai jamais vu, mais cela semble logique.

Au début, il commande par s.type != 'Nails'. Il s'agit de false pour chaque ligne contenant Nails dans la colonne type. Après cela, il est trié par Bolts. Encore une fois pour toutes les colonnes qui contiennent Bolts en tant que type, cela a la valeur false. Etc.

Un petit test révèle que false est commandé avant true. Vous disposez donc des éléments suivants: vous obtenez d'abord toutes les lignes avec Nails en haut parce que le ORDER BY évalué en false et false vient en premier. Les lignes restantes sont triées par le deuxième ORDER BY critère. Etc.

 type | ! = Ongles | ! = Boulons | ! = Rondelles 
 'Clous' | faux | vrai | true 
 'Boulons' | vrai | faux | true 
 'Rondelles' | vrai | vrai | faux
36
musiKk

Chaque expression est évaluée comme un booléen et traitée comme 0 pour faux et 1 pour vrai et triée de manière appropriée. Même si cela fonctionne, la logique est difficile à suivre (et donc à maintenir). Ce que j'utilise est une fonction qui trouve l'index d'une valeur dans un tableau.

ORDER BY idx(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)

C'est beaucoup plus facile à suivre. Les ongles seront triés en premier et les noix en dernier. Vous pouvez voir comment créer la fonction idx dans le référentiel d'extraits de code Postgres. http://wiki.postgresql.org/wiki/Array_Index

51
Scott Bailey

@ Scott Bailey a suggéré une excellente idée. Mais cela peut être encore plus simple (vous n'avez pas à créer de fonction personnalisée) depuis PostgreSQL 9.5. Utilisez simplement array_position fonction:

ORDER BY array_position(array['Nails','Bolts','Washers','Screws','Staples','Nuts'], s.type)
35
Daniil Ryzhkov

avec array_position, il doit avoir le même type que celui sur lequel vous interrogez.

par exemple:

select array_position(array['foo'::char,'bar','baz'::char], 'bar');
select array_position(array['foo'::char,'bar','baz'::char], 'baz'::char);
6
lifeiscontent