首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL高效最近邻查询

SQL高效最近邻查询
EN

Stack Overflow用户
提问于 2009-04-06 09:25:41
回答 4查看 9.5K关注 0票数 7

我想不出一个有效的SQL查询来处理以下情况:

假设我们有一个包含两列的表

代码语言:javascript
复制
groupId : int 
value : float

这个表很大(几百万行)。每个"groupId“都有不同数量的”值“--比如在100%到50.000之间。所有浮点值都大于或等于零,但在其他情况下是无界的。

对于给定的groupId,查询应返回按相似度递减排序的所有其他组,其中“相似”定义为两组中所有可能的30个值对之间的最小欧几里得距离。

这种相似性的定义让我很难受。我认为对于上面定义的相似度计算,朴素算法是O(n^2)。现在,我正在寻找重新定义“相似性”或有效实现上述内容的想法。我可以想象一种涉及k近邻的解决方案,比如PostGis几何近邻,或者可能是一个最大的公共子序列算法(尽管我需要后者的“模糊”实现,因为“值”很难完全相等)。

我们目前在mySQL上,以防万一。

干杯,

代码语言:javascript
复制
Sören
EN

回答 4

Stack Overflow用户

发布于 2009-04-06 19:14:23

你能证实我答对了吗?

您的表表示由groupId标识的向量。每个向量都有一个介于100和50,000之间的维度,但维度上没有定义顺序。也就是说,表中的向量实际上是等价类的代表。

现在,您将两个等价类的相似性定义为等价类的任意两个表示到前30维的子空间的投影的最小欧几里得距离。

投影到二维的示例:

代码语言:javascript
复制
A = <1, 2, 3, 4>
B = <5, 6, 7, 8, 9, 10>

A表示向量的下列等价类。

代码语言:javascript
复制
<1, 2, 3, 4>    <2, 1, 2, 3>    <3, 1, 2, 4>    <4, 1, 2, 3>
<1, 2, 4, 4>    <2, 1, 3, 2>    <3, 1, 4, 2>    <4, 1, 3, 2>
<1, 3, 2, 4>    <2, 3, 1, 4>    <3, 2, 1, 4>    <4, 2, 1, 3>
<1, 3, 4, 2>    <2, 3, 4, 1>    <3, 2, 4, 1>    <4, 2, 3, 1>
<1, 4, 2, 2>    <2, 4, 1, 3>    <3, 4, 1, 2>    <4, 3, 1, 2>
<1, 4, 3, 2>    <2, 4, 3, 1>    <3, 4, 2, 1>    <4, 3, 2, 1>

这个等价类的所有代表到前两个维度的投影产生。

代码语言:javascript
复制
<1, 2>    <1, 3>    <1, 4>
<2, 1>    <2, 3>    <2, 4>
<3, 1>    <3, 2>    <3, 4>
<4, 1>    <4, 2>    <4, 3>

B表示具有720个元素的等价类。到前两个维度的投影产生30个元素。

代码语言:javascript
复制
< 5, 6>    < 5, 7>    < 5, 8>    < 5, 9>    < 5, 10>
< 6, 5>    < 6, 7>    < 6, 8>    < 6, 9>    < 6, 10>
< 7, 5>    < 7, 6>    < 7, 8>    < 7, 9>    < 7, 10>
< 8, 5>    < 8, 6>    < 8, 7>    < 8, 9>    < 8, 10>
< 9, 5>    < 9, 6>    < 9, 7>    < 9, 8>    < 9, 10>
<10, 5>    <10, 6>    <10, 7>    <10, 8>    <10,  9>

所以A和B的距离是8的平方根,因为这是两个向量到投影的最小距离。例如<3,4>和<5,6>产生这个距离。

那么,我对这个问题的理解是正确的吗?

对于每个具有m个分量的n个向量,一个非常朴素的算法必须计算(n - 1)个距离。对于每个距离,算法将计算m!/ (m - 30)的距离!每个向量的投影。因此,对于100维(你的下限),一个向量有2.65*10^32个可能的投影。这需要计算投影之间大约7*10^64的距离,并找到最小值来找到两个向量的距离。然后重复n次。

我希望我误解了你的意思或者弄错了。否则,这听起来真的很有挑战性,也不可行。

我考虑的是对向量分量进行排序并尝试匹配它们。如果可能的话,使用曼哈顿距离可能有助于简化解决方案。

票数 4
EN

Stack Overflow用户

发布于 2009-04-07 01:47:45

以下是一些很好的近似值:

您可以计算每组的质心,然后根据每组质心的距离进行比较。

另一种方法是散列每一行的坐标,散列到相同位置的行被认为是相似的,因此两组相似性被更新。

一些更多的信息将会有所帮助,例如:

信息是否不断更新?如果是,更新时间间隔是多少。它有多新?它需要多精确?

票数 1
EN

Stack Overflow用户

发布于 2009-04-07 02:21:39

简单的版本应该是这样的:(不是通过查询分析器运行)

代码语言:javascript
复制
select groupid, min(distance) as mindist
from
   (select other.groupid as groupid,
           min(abs(other.value - us.value)) as distance
    from g us
    join g other on other.groupid != us.groupid
    where us.groupid = ?)
order by mindist
group by groupid

然后,为了利用索引:

代码语言:javascript
复制
select groupid, min(abs(value - usvalue)) as mindist
from
   (select other.groupid as groupid,
           max(other.value) as value,
           us.value as usvalue
    from g us
    join g other on other.groupid != us.groupid and other.value <= us.value
    where us.groupid = ?

    union

    select other.groupid as groupid,
           min(other.value) as value,
           us.value as usvalue
    from g us
    join g other on other.groupid != us.groupid and other.value >= us.value
    where us.groupid = ?)
order by mindist
group by groupid

这将有望允许mysql使用索引来快速找到连接上最近的邻居。

这里面可能有错误,但希望这条思路能有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/720773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档