PostgreSQL hỗ trợ toán tử khoảng cách <->
và như tôi hiểu, điều này có thể được sử dụng để phân tích văn bản (với mô-đun pg_trgrm) và hình học
kiểu dữ liệu.
Tôi không biết làm thế nào bạn có thể sử dụng nó với nhiều hơn 1 chiều. Có thể bạn sẽ phải xác định hàm khoảng cách của riêng mình hoặc bằng cách nào đó chuyển đổi dữ liệu của bạn thành một cột với kiểu văn bản hoặc hình học. Ví dụ:nếu bạn có bảng có 8 cột (hình khối 8 chiều):
c1 c2 c3 c4 c5 c6 c7 c8
1 0 1 0 1 0 1 2
Bạn có thể chuyển đổi nó thành:
c1 c2 c3 c4 c5 c6 c7 c8
a b a b a b a c
Và sau đó đến bảng có một cột:
c1
abababac
Sau đó, bạn có thể sử dụng (sau khi tạo gist
chỉ mục
):
SELECT c1, c1 <-> 'ababab'
FROM test_trgm
ORDER BY c1 <-> 'ababab';
Ví dụ
Tạo dữ liệu mẫu
-- 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)
);
Chuyển dữ liệu đầu vào thành văn bản
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
);
Điều này sẽ cung cấp cho bạn một biến trans_variable
nơi lưu trữ tất cả 8 thứ nguyên:
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
Thay vì ||
bạn cũng có thể sử dụng cú pháp sau (ngắn hơn, nhưng khó hiểu hơn):
select
array_to_string(string_to_array(t.*::text,''),'') as trans_variable
from
tmp.test_data t
Thêm chỉ mục
create index test_data_gist_index on tmp.test_data_trans using gist(trans_variable);
Khoảng cách kiểm tra Lưu ý:Tôi đã chọn một hàng từ bảng - 52;42;18;50;68;29;8;55
- và sử dụng giá trị đã thay đổi một chút (42;42;18;52;98;29;8;55
) để kiểm tra khoảng cách. Tất nhiên, bạn sẽ có các giá trị hoàn toàn khác trong dữ liệu thử nghiệm của mình, vì đó là ma trận NGẪU NHIÊN.
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';
Bạn có thể sử dụng toán tử khoảng cách <-> hoặc hàm tương tự. Khoảng cách =1 - Độ giống nhau