我试图为此找到解决方案,当记录低于某个数字时,它在某种程度上很容易解决。但...
我有一份包含81,590条记录的原始列表。
Id Loc Sales LatLong
1 a 100 ...
2 b 110 ...
3 c 105 ...
4 d 125 ...
5 e 123 ...
6 f 35 ...
.
.
.
81,590 ... ... ...
我需要将列表中的所有项目相互比较。
Id L1 L2 Dist
1 a a 0 --> Not needed. Self comparison.
2 a b 26
3 a c 150 --> Not needed. Distance >100.
4 a d 58
5 b a 26 --> Not needed. Repeated record.
6 b b 0 --> Not needed. Self comparison.
7 b c 15
8 b d 151 --> Not needed. Distance >100.
9 c a 150 --> Not needed. Repeated record.
10 c b 15 --> Not needed. Repeated record.
11 c c 0 --> Not needed. Self comparison.
12 c d 75
13 d a 58 --> Not needed. Repeated record.
14 d b 151 --> Not needed. Repeated record.
15 d c 75 --> Not needed. Repeated record.
16 d d 0 --> Not needed. Self comparison.
但如上面记录旁边所示,最终结果必须是以下列表:
1)仅当记录位于特定距离时(例如<100英里),才能将记录相互比较。
2)在将Loc1与Loc2进行比较与将Loc2与Loc1进行比较相同的意义上,不包含重复项。
3)显而易见的是,无需将Loc1与自身进行比较。
最终结果将是:
Id L1 L2 Dist
2 a b 26
4 a d 58
7 b c 15
12 c d 75
方法:
理论上,将所有项目与自己进行比较后的记录总数为81,590 ^ 2 = 6,656,928,100条记录。
减去重复的迭代次数(LocA-LocB = LocB-LocA)意味着6,656,928,100 / 2 = 3,328,464,050。
通过摆脱自重复迭代(LocA-LocA)进一步清理,应为3,328,464,050 - 81,590 = 3,328,382,460。
然后我可以摆脱所有带距离的记录&gt; 100英里。
这是非常低效的,我正在构建一个包含6Bn记录的表,然后删除一半等等。
是否有方法以更高效(更少步骤,更少选择/删除/更新)的方式到达最终产品?
将最终数据集插入目标所需的select语句是什么?
听起来像是表格与自身的连接以及按键的迭代过滤,但这里是我被卡住的地方。
答案 0 :(得分:0)
您使用什么算法来计算两点之间的距离?简单的“世界是扁平的”笛卡尔数学,或那个三角函数“这个词是扁圆形的”是一个吗?这可能会变成严重的CPU要求。
最好生成一个“位于该位置距离X内的位置”的表格,并将其永久存储;除非像地震这样的重大事件,否则它不会改变。
查询方面,基本连接很简单:
SELECT
t1.Loc L1
,t2.Loc L2
from MyTable t1
inner join MyTable t2
on t2.Loc > t1.Loc
如果在名为“distanceFunction”的函数中有距离公式,它可能看起来像:
WITH cteCalc as (
select
t1.Loc L1
,t2.Loc L2
,dbo.distanceFunction(t1.LatLong, t2.LatLong) Dist
from MyTable t1
inner join MyTable t2
on t2.Loc > t1.Loc
where dbo.distanceFunction(t1.LatLong, t2.LatLong) < @MaxDistance)
INSERT TargetTable (L1, L2, Dist)
SELECT
L1
,L2
,Dist
where Dist <= @MaxDistance
当然,这可能会破坏您的系统,只是因为当您向目标表写入数十亿行时,事务日志会变得太大。我说要构建一个循环,依次处理每个位置,最后的查询如下:
WITH cteCalc as (
select
t1.Loc L1
,t2.Loc L2
,dbo.distanceFunction(t1.LatLong, t2.LatLong) Dist
from MyTable t1
inner join MyTable t2
on t2.Loc > t1.Loc
where dbo.distanceFunction(t1.LatLong, t2.LatLong) < @MaxDistance
and t1.Loc = @ThisIterationLoc)
INSERT TargetTable (L1, L2, Dist)
SELECT
L1
,L2
,Dist
where Dist <= @MaxDistance
第一次传球返回81,589,无论哪个太远,第二次传球为81,588,等等。
答案 1 :(得分:0)
以下是我将如何解决此问题的概述:
对距离范围(方框)的lat和长距离进行数学计算。然后你知道你的距离(如方框不是圆圈)包含在这个三角形中。你也知道它不在这个三角洲之外。这大大限制了这个问题。
例如,如果lat和long的变化对于你的距离是10,那么你的盒子的位置(100,100)将由lat和long的(95,95)和(105,105)值定义。 / EM>