The ORDER BY clause is decribed in the PostgreSQLdocumentation as:
ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]
Can someone give me some examples how to use the USING operator? Is it possible to get an alternating order of the resultset?
A very simple example would be:
But this is boring, because this is nothing you can’t get with the traditional
ORDER BY col ASC.Also the standard catalog doesn’t mention anything exciting about strange comparison functions/operators. You can get a list of them:
You will notice, that there are mostly
<and>functions for primitive types likeinteger,dateetc and some more for arrays and vectors and so on. None of these operators will help you to get a custom ordering.In most cases where custom ordering is required you can get away using something like
... ORDER BY somefunc(tablecolumn) ...wheresomefuncmaps the values appropriately. Because that works with every database this is also the most common way. For simple things you can even write an expression instead of a custom function.Switching gears up
ORDER BY ... USINGmakes sense in several cases:somefunctrick doesn’t work.point,circleor imaginary numbers) and you don’t want to repeat yourself in your queries with strange calculations.I will focus on the complex datatypes: often there is more than one way to sort them in a reasonable way. A good example is
point: You can “order” them by the distance to (0,0), or by x first, then by y or just by y or anything else you want.Of course, PostgreSQL has predefined operators for
point:But none of them is declared usable for
ORDER BYby default (see above):Simple operators for
pointare the “below” and “above” operators<^and>^. They compare simply theypart of the point. But:ORDER BY USINGrequires an operator with defined semantics: Obviously it must be a binary operator, it must accept the same type as arguments and it must return boolean. I think it must also be transitive (if a < b and b < c then a < c). There may be more requirements. But all these requirements are also necessary for proper btree-index ordering. This explains the strange error messages containing the reference to btree.ORDER BY USINGalso requires not just one operator to be defined but an operator class and an operator family. While one could implement sorting with only one operator, PostgreSQL tries to sort efficiently and minimize comparisons. Therefore, several operators are used even when you specify only one – the others must adhere to certain mathematical constraints – I’ve already mentioned transitivity, but there are more.Switching Gears up
Let’s define something suitable: An operator for points which compares only the
ypart.The first step is to create a custom operator family which can be used by the btree index access method. see
Next we must provide a comparator function which returns -1, 0, +1 when comparing two points. This function WILL be called internally!
Next we define the operator class for the family. See the manual for an explanation of the numbers.
This step combines several operators and functions and also defines their relationship and meaning. For example
OPERATOR 1means: This is the operator forless-thantests.Now the operators
<^and>^can be used inORDER BY USING:Voila – sorted by y.
To sum it up:
ORDER BY ... USINGis an interesting look under the hood of PostgreSQL. But nothing you will require anytime soon unless you work in very specific areas of database technology.Another example can be found in the Postgres docs. with source code for the example here and here. This example also shows how to create the operators.