PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Creazione di un operatore di uguaglianza personalizzato per il tipo PostgreSQL (punto) per le chiamate DISTINCT

Per selezionare valori distinti, Postgres deve avere la possibilità di ordinare la colonna. Devi creare un btree completo classe operatore per type point, ovvero cinque operatori (< , <= , = , >= , > ) e una funzione che confronta due punti e restituisce un intero, come descritto in il documentazione .

Per l'operatore = puoi usare la funzione esistente point_eq(point, point) :

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

Esempio di definizione dell'operatore < :

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

Definisci gli operatori <= , => e > in un modo simile. Avendo tutti e cinque gli operatori, crea una funzione:

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

E infine:

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

Con la classe point_ops definito puoi selezionare valori di punti distinti e ordinare le righe in base alla colonna di tipo punto, ad es.:

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)    

Puoi anche creare un indice (unico) su una colonna di punti.

Aggiornare.

Postgres ha oltre 2800 funzioni ausiliarie che supportano operatori, indici, funzioni standard, ecc. Puoi elencarle interrogando pg_proc , es.:

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

La funzione point_eq(point, point) viene utilizzato in implementazione di alcune funzioni e operatori geometrici.