web-dev-qa-db-fra.com

Clause "ORDER BY ... USING" dans PostgreSQL

La clause ORDER BY est décrite dans la documentation de PostgreSQL comme suit:

ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]

Quelqu'un peut-il me donner des exemples d'utilisation du USING operator? Est-il possible d’obtenir un ordre alternatif des résultats?

37
markus

Échantillons:

CREATE TABLE test
(
  id serial NOT NULL,
  "number" integer,
  CONSTRAINT test_pkey PRIMARY KEY (id)
)

insert into test("number") values (1),(2),(3),(0),(-1);

select * from test order by number USING > //gives 3=>2=>1=>0=>-1

select * from test order by number USING < //gives -1=>0=>1=>2=>3

Donc, cela équivaut à desc et asc. Mais vous pouvez utiliser votre propre opérateur, c'est la caractéristique essentielle de USING

4
J0HN

De bonnes réponses, mais ils n'ont pas mentionné un cas de grande valeur pour USING. 

Lorsque vous créez un index avec une famille d’opérateurs autres que celle par défaut, par exemple varchar_pattern_ops (~> ~, ~ <~, ~> = ~ ...) au lieu de <,>,> = ..., si vous effectuez une recherche sur index et vous vous souhaitez utiliser index dans la clause order by, vous devez spécifier USING avec l'opérateur approprié. 

Ceci peut être illustré avec cet exemple:

CREATE INDEX index_words_Word ON words(Word text_pattern_ops); 

Permet de comparer ces deux requêtes:

SELECT * FROM words WHERE Word LIKE 'o%' LIMIT 10;

et

SELECT * FROM words WHERE Word LIKE 'o%' ORDER BY Word LIMIT 10;

La différence entre leurs exécutions est presque 100 fois à 500K mots DB! Et aussi les résultats peuvent ne pas être corrects dans les paramètres régionaux non-C 

Comment cela pourrait se passer? 

Lorsque vous effectuez une recherche avec les clauses LIKE et ORDER BY, vous effectuez cet appel:

SELECT * FROM words WHERE Word ~>=~ 'o' AND Word ~<~'p' ORDER BY Word USING < LIMIT 10;

Votre index étant créé avec l’opérateur ~ <~ à l’esprit, PG ne peut donc pas utiliser un index donné dans une clause ORDER BY donnée. Pour que les choses soient bien faites, la requête doit être réécrite sous cette forme:

SELECT * FROM words WHERE Word ~>=~ 'o' AND Word ~<~'p' ORDER BY Word USING ~<~ LIMIT 10;

ou

SELECT * FROM words WHERE Word LIKE 'o%' ORDER BY Word USING ~<~ LIMIT 10;

On peut éventuellement ajouter la clé Word ASC (croissant) ou DESC (décroissant) après toute expression de la clause ORDER BY. Si non spécifié, ASC est supposé par défaut. Alternativement, un .__ spécifique. Le nom de l'opérateur de commande peut être spécifié dans la clause USING. Un opérateur de commande doit être un membre inférieur ou supérieur à certains Famille d'opérateurs B-tree. ASC est généralement équivalent à USING <et DESC est généralement équivalent à USING>.

PostgreSQL 9.0

Cela peut ressembler à quelque chose comme ceci, je pense (je n'ai pas postgres pour vérifier cela maintenant, mais vérifierai plus tard)

SELECT Name FROM Person
ORDER BY NameId USING >
0
VoodooChild