PostgreSQL поддерживает оператор расстояния <->
, и, насколько я понимаю, его можно использовать для анализа текста (с модулем pg_trgrm) и геометрия тип данных.
Я не знаю, как вы можете использовать его с более чем 1 измерением. Возможно, вам придется определить свою собственную функцию расстояния или как-то преобразовать ваши данные в один столбец с текстовым или геометрическим типом. Например, если у вас есть таблица с 8 столбцами (8-мерный куб):
c1 c2 c3 c4 c5 c6 c7 c8
1 0 1 0 1 0 1 2
Вы можете преобразовать его в:
c1 c2 c3 c4 c5 c6 c7 c8
a b a b a b a c
А затем в таблицу с одним столбцом:
c1
abababac
Затем вы можете использовать (после создания gist
индекса):
SELECT c1, c1 <-> 'ababab'
FROM test_trgm
ORDER BY c1 <-> 'ababab';
Пример
Создать образец данных
-- Create some temporary data
-- ! Note that table are created in tmp schema (change sql to your scheme) and deleted if exists !
drop table if exists tmp.test_data;
-- Random integer matrix 100*8
create table tmp.test_data as (
select
trunc(random()*100)::int as input_variable_1,
trunc(random()*100)::int as input_variable_2,
trunc(random()*100)::int as input_variable_3,
trunc(random()*100)::int as input_variable_4,
trunc(random()*100)::int as input_variable_5,
trunc(random()*100)::int as input_variable_6,
trunc(random()*100)::int as input_variable_7,
trunc(random()*100)::int as input_variable_8
from
generate_series(1,100,1)
);
Преобразование входных данных в текст
drop table if exists tmp.test_data_trans;
create table tmp.test_data_trans as (
select
input_variable_1 || ';' ||
input_variable_2 || ';' ||
input_variable_3 || ';' ||
input_variable_4 || ';' ||
input_variable_5 || ';' ||
input_variable_6 || ';' ||
input_variable_7 || ';' ||
input_variable_8 as trans_variable
from
tmp.test_data
);
Это даст вам одну переменную trans_variable
, в которой хранятся все 8 измерений:
trans_variable
40;88;68;29;19;54;40;90
80;49;56;57;42;36;50;68
29;13;63;33;0;18;52;77
44;68;18;81;28;24;20;89
80;62;20;49;4;87;54;18
35;37;32;25;8;13;42;54
8;58;3;42;37;1;41;49
70;1;28;18;47;78;8;17
Вместо оператора ||
вы также можете использовать следующий синтаксис (более короткий, но более загадочный):
select
array_to_string(string_to_array(t.*::text,''),'') as trans_variable
from
tmp.test_data t
Добавить индекс
create index test_data_gist_index on tmp.test_data_trans using gist(trans_variable);
Тестовое расстояние Примечание. Я выбрал одну строку из таблицы — 52;42;18;50;68;29;8;55
— и использовал слегка измененное значение (42;42;18;52;98;29;8;55
) для проверки расстояния. Конечно, у вас будут совершенно другие значения в ваших тестовых данных, потому что это СЛУЧАЙНАЯ матрица.
select
*,
trans_variable <-> '42;42;18;52;98;29;8;55' as distance,
similarity(trans_variable, '42;42;18;52;98;29;8;55') as similarity,
from
tmp.test_data_trans
order by
trans_variable <-> '52;42;18;50;68;29;8;55';
Вы можете использовать оператор расстояния ‹-> или функцию подобия. Расстояние = 1 - Сходство
person
Tomas Greif
schedule
22.05.2013