在大表中查询“对”

Posted

技术标签:

【中文标题】在大表中查询“对”【英文标题】:Querying "pairs" in large table 【发布时间】:2017-01-26 11:50:26 【问题描述】:

更新

我在 SQL Server 2014 中有一个大表,我需要在其中找到与关键字段中每个值之间所需的接近度相对应的“对”。在现实生活中,它是通过给定的接近度搜索所有位置,没有搜索区域的中心。关键字段的数据类型为 Geography,并填充了地图上的坐标点。

create table data
(
   id        int, 
   keyfield  geography
);

id    keyfield
-------------- 
1          a,b 
2          g,h
3          c,d
4          k,l
5          x,z

当搜索距离小于 N 的位置对时,预期结果为

id1   id2
------------- 
1     3      <- distance between 1 and 3 is less than N
2     4      <- distance between 2 and 4 is less than N

到目前为止(感谢 cmets 关于“重复”)我有

select t1.id, t2.id,  
from data t1, data t2  
where t1.keyfield.STDistance(t2.keyfield) < N
and t1.id < t2.id

create table search
(
   id1 int,
   id2 int 
);
--------------

declare @id int  
declare @g geography

declare c cursor for  
select id, keyfield from data

open c   
fetch next from c into @id, @g   

while @@fetch_status = 0   
begin   
       insert into search
       select @id, id from data
       where keyfield.STDistance(@g) < N
       and @id < id

       fetch next from c into @id, @g
end   

close c   
deallocate c

即使在记录数为 10-20K 的小集合上,两者的运行速度也慢得让人无法接受。

同样,它不是从中心 Point(y,z) 开始搜索 N 半径内的位置,而是搜索彼此之间距离为 N 的所有位置。

【问题讨论】:

where中使用t1.id &lt; t2.id 现实生活中的keyfield不是数字而是其他值 如果 keyfield 不是数字,你如何计算 50 的差异? 演示是可以解决的,然而,真正的用例是一个黑盒子。 Isee,那么为了清楚起见,您可以使用特殊字符串来显示。 【参考方案1】:

假设你的“距离”函数是对称的,那么:

select t1.id, t2.id
from table1 t1 cross join
     table2 t2
     on t1.id < t2.id and myfunction(t1.keyfield, t2.keyfield) < 50;

这在一张大桌子上会很昂贵,所以它可能无法解决您的实际问题。

我建议您再问一个问题,提供更多信息和示例,了解字段是什么样的以及“距离”函数的逻辑是什么。

【讨论】:

【参考方案2】:
 select t1.id, t2.id
 from table1 t1
 join table1 t2
   ON t2.id between t1.keyfield - 50 and t1.keyfield + 50
  AND t1.id < t2.id

【讨论】:

【参考方案3】:

您可以像这样指定JOIN 条件的差异:

CREATE TABLE #Table1
    ([id] int, [keyfield] int)
;

INSERT INTO #Table1
    ([id], [keyfield])
VALUES
    (1, 100),
    (2, 200),
    (3, 130),
    (4, 201),
    (5, 999);

SELECT t1.id ,
       t1.keyfield ,
       t2.id,
       t2.keyfield
FROM #Table1 t1
INNER JOIN #Table1 t2 ON t2.keyfield <= t1.keyfield + 50 AND t2.keyfield > t1.keyfield

DROP TABLE #Table1

输出:

id  keyfield    id  keyfield
1   100         3   130
2   200         4   201

这没有考虑到您的功能,因为您没有指定它的作用。因此,我删除了 WHERE 子句,这可能会为您提供另一种方法。

【讨论】:

以上是关于在大表中查询“对”的主要内容,如果未能解决你的问题,请参考以下文章

MySQL查询在大表上很慢

Excel函数在大表中查找重复行

JPA 存储库:将实体保存在大表中的问题 - 超时错误 [重复]

蟒蛇:MYSQLdb。如何在不执行 select * 在大表中获取列名?

在大表中计算未读新闻

如何使用具有多个 GROUP BY、子查询和 WHERE IN 在大表上的查询来优化查询?