PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Création d'un opérateur d'égalité personnalisé pour le type PostgreSQL (point) pour les appels DISTINCT

Pour sélectionner des valeurs distinctes, Postgres doit avoir la capacité de trier la colonne. Vous devez créer un btree complet classe d'opérateur pour le type point, soit cinq opérateurs (< , <= , = , >= , > ) et une fonction comparant deux points et renvoyant un entier, comme décrit dans le documents .

Pour l'opérateur = vous pouvez utiliser la fonction existante point_eq(point, point) :

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

Exemple de définition de l'opérateur < :

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 = >);

Définir les opérateurs <= , => et > d'une manière similaire. Ayant les cinq opérateurs, créez une fonction :

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
$$;

Et enfin :

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);

Avec la classe point_ops défini, vous pouvez sélectionner des valeurs de point distinctes et trier les lignes par la colonne de type point, par exemple :

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)    

Vous pouvez également créer un index (unique) sur une colonne de points.

Mise à jour.

Postgres a plus de 2800 fonctions auxiliaires qui prennent en charge les opérateurs, les index, les fonctions standard, etc. Vous pouvez les lister en interrogeant pg_proc , par exemple :

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

La fonction point_eq(point, point) est utilisé dans l'implémentation de certaines fonctions et opérateurs géométriques.