sql >> Base de Datos >  >> RDS >> PostgreSQL

Creación de un operador de igualdad personalizado para el tipo PostgreSQL (punto) para llamadas DISTINCT

Para seleccionar valores distintos, Postgres debe tener la capacidad de ordenar la columna. Debe crear un btree completo clase de operador para tipo punto, es decir, cinco operadores (< , <= , = , >= , > ) y una función que compara dos puntos y devuelve un número entero, como se describe en the documentación .

Para el operador = puede usar la función existente point_eq(point, point) :

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

Ejemplo de definición del operador < :

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

Definir los operadores <= , => y > en una manera similar. Teniendo los cinco operadores, crea una función:

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

Y finalmente:

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 clase point_ops definido, puede seleccionar distintos valores de puntos y ordenar filas por la columna de tipo de punto, por ejemplo:

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)    

También puede crear un índice (único) en una columna de puntos.

Actualizar.

Postgres tiene más de 2800 funciones auxiliares que admiten operadores, índices, funciones estándar, etc. Puede enumerarlas consultando pg_proc , por ejemplo:

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

La función point_eq(point, point) se utiliza en la implementación de algunas operadores y funciones geométricas .