PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Erstellen eines benutzerdefinierten Gleichheitsoperators für den PostgreSQL-Typ (Punkt) für DISTINCT-Aufrufe

Um eindeutige Werte auszuwählen, muss Postgres in der Lage sein, die Spalte zu sortieren. Sie müssen einen vollständigen btree erstellen Operatorklasse für Typpunkt, also fünf Operatoren (< , <= , = , >= , > ) und eine Funktion, die zwei Punkte vergleicht und eine ganze Zahl zurückgibt, wie sie in beschrieben ist Dokumentation .

Für den Operator = Sie können die vorhandene Funktion point_eq(point, point) verwenden :

create operator = (leftarg = point, rightarg = point, procedure = point_eq, commutator = =);

Beispieldefinition des Operators < :

create function point_lt(point, point)
returns boolean language sql immutable as $$
    select $1[0] < $2[0] or $1[0] = $2[0] and $1[1] < $2[1]
$$;

create operator < (leftarg = point, rightarg = point, procedure = point_lt, commutator = >);

Definieren Sie die Operatoren <= , => und > auf eine ähnliche Art und Weise. Erstellen Sie mit allen fünf Operatoren eine Funktion:

create function btpointcmp(point, point)
returns integer language sql immutable as $$
    select case 
        when $1 = $2 then 0
        when $1 < $2 then -1
        else 1
    end
$$;

Und schließlich:

create operator class point_ops
    default for type point using btree as
        operator 1 <,
        operator 2 <=,
        operator 3 =,
        operator 4 >=,
        operator 5 >,
        function 1 btpointcmp(point, point);

Mit der Klasse point_ops definiert, können Sie unterschiedliche Punktwerte auswählen und Zeilen nach der Spalte vom Typ Punkt anordnen, z. B.:

with q(p) as (
    values 
        ('(1,1)'::point),
        ('(1,2)'::point),
        ('(2,1)'::point),
        ('(1,1)'::point))
select distinct *
from q
order by 1 desc;

   p   
-------
 (2,1)
 (1,2)
 (1,1)
(3 rows)    

Sie können auch einen (eindeutigen) Index für eine Punktspalte erstellen.

Aktualisieren.

Postgres hat über 2800 Hilfsfunktionen, die Operatoren, Indizes, Standardfunktionen usw. unterstützen. Sie können sie auflisten, indem Sie pg_proc , zB:

select format('%s(%s)', proname, pg_get_function_arguments(oid))
from pg_proc
where pronamespace::regnamespace = 'pg_catalog'
and proname like 'point%'

Die Funktion point_eq(point, point) wird bei der Implementierung einiger geometrischen Funktionen und Operatoren. verwendet