PostgreSQL创建函数欧几里得距离n维

top*_*opo 5 postgresql

我在PostgreSQL中是菜鸟,我正在尝试创建一个函数来计算特定值和一组值(记录)之间的距离。表格如下:

CREATE TABLE test
(
  id serial NOT NULL,
  name text,
  values real[]
)   
Run Code Online (Sandbox Code Playgroud)

我想创建一个函数,但是我不知道如何循环值中的每个元素[]

例如,我想选择距离最小的名称。我没有为此目的找到任何内置函数。

我用C#编写了要查找的代码:

List<double> res = new List<double>();
List<double[]> listDataBase=new List<double[]>();
double[] query = new double[] {12, 13, 13, 121};

double[] b = new double[] { 121, 1, 12, 124 };
double[] c = new double[] { 123, 123, 15, 122 };
double[] d = new double[] { 121, 1, 12, 124 };
double[] e = new double[] { 123, 123, 15, 122 };
listDataBase.Add(b);
listDataBase.Add(c);
listDataBase.Add(d);
listDataBase.Add(e);
foreach (double[] k  in listDataBase)
{
    double sum = 0;
    for (int i = 0; i < query.Length; i++)
    {
        sum += Math.Pow(query[i] - k[i], 2);
    }
    res.Add(Math.Sqrt(sum));
}

res.Sort();
Run Code Online (Sandbox Code Playgroud)

Eel*_*lke 5

首先,我会将您称为 value 的列的名称更改为 vals。值是一个关键字,当然您可以在查询中写入“值”,但我更愿意通过更改名称来规避该问题。

如果我正确理解你的问题,我认为在你的情况下创建一个距离函数然后在查询中使用它就足够了。这是函数:

CREATE OR REPLACE FUNCTION distance(l real[], r real[]) RETURNS real AS $$
DECLARE
  s real;
BEGIN
  s := 0;
  FOR i IN 1..4 LOOP
    s := s + ((l[i] - r[i]) * (l[i] - r[i]));
  END LOOP;
  RETURN |/ s;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

如果您想要最接近的名称,则查询是:

SELECT name
FROM test
ORDER BY distance(test.values, ARRAY[12, 13, 13, 121]) DESC
LIMIT 1
Run Code Online (Sandbox Code Playgroud)