Para selecionar valores distintos, o Postgres deve ter a capacidade de classificar a coluna. Você precisa criar uma btree completa classe de operador para ponto de tipo, ou seja, cinco operadores (
<
, <=
, =
, >=
, >
) e uma função comparando dois pontos e retornando inteiro, conforme descrito no the documentação
. Para o operador
=
você pode usar a função existente point_eq(point, point)
:create operator = (leftarg = point, rightarg = point, procedure = point_eq, commutator = =);
Exemplo de definição do 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 = >);
Defina os operadores
<=
, =>
e >
de maneira semelhante. Tendo todos os cinco operadores, crie uma função: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 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);
Com a classe
point_ops
definido, você pode selecionar valores de pontos distintos e ordenar as linhas pela coluna do tipo de ponto, por exemplo: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)
Você também pode criar um índice (único) em uma coluna de ponto.
Atualizar.
Postgres tem mais de 2800 funções auxiliares que suportam operadores, índices, funções padrão, etc. Você pode listá-los consultando
pg_proc
,
por exemplo.:select format('%s(%s)', proname, pg_get_function_arguments(oid))
from pg_proc
where pronamespace::regnamespace = 'pg_catalog'
and proname like 'point%'
A função
point_eq(point, point)
é usado na implementação de algumas funções e operadores geométricos.