【问题标题】:Finding the closest location in Table2 for each location in Table1为表 1 中的每个位置在表 2 中查找最近的位置
【发布时间】:2017-09-21 10:18:55
【问题描述】:

我目前使用的mySQL数据库有两个表:一个叫source,另一个叫siteinfo

siteinfo表如图:

+-----------+----------+----------+
| longitude | latitude | sitecode |
+-----------+----------+----------+
|    1.3009 | 1.900989 |        2 |
+-----------+----------+----------+
|    1.7034 | 1.20034  |        3 |
+-----------+----------+----------+

同样,源表如下图:

+-----------+----------+----------+
| longitude | latitude | sitecode |
+-----------+----------+----------+
|    1.3009 | 1.900989 |   NULL   |
+-----------+----------+----------+

我的主要目标是:

对于source 表中的每一行,我想获取名为经度和纬度的列,并将它们与siteinfo 表中相应的经度和纬度列进行比较。

Source 表中 Long 和 Lat 行与 siteinfo 表中的行最相似的那些行,然后使用 @987654331 中 sitecode 列的相应 sitecode 更新 sitecode 列@表。

例如,源表中的 long 和 lat 值与 siteinfo 表的第一行中的值最接近,因此 sitecode 更新为 2。

为了解决这个问题,我知道我必须创建两个结果集并使用 while(next()) 来遍历每个结果集的每一行。问题是,我如何比较以找到最相似的条目?

我想到了蛮力,使用 For 循环来比较源结果集的第一行条目与 Siteinfo 结果集的每一行然后递增到第二行。

但是,我理解 next() 函数对每一行的结果集工作,这与 for 循环不同,因为我想将一个结果集的第一行与另一个结果集的每一行进行比较。

二、如何找到两个结果表的一个列条目的差异?

【问题讨论】:

  • 你应该看看 MySQL 是否支持空间数据类型和查询。然后你可以通过对服务器的单个查询来完成它,而不是结合笨拙的 Java 代码来做你想做的事情。

标签: java mysql database jdbc


【解决方案1】:

不,您不必创建两个结果集。您可以创建一个 MySQL 函数来计算两点之间的Great Circle Distance ...

CREATE FUNCTION great_circle_km (lon1 DOUBLE, lat1 DOUBLE, lon2 DOUBLE, lat2 DOUBLE)
RETURNS DOUBLE
RETURN 6371 * acos(cos(radians(lat1)) * cos(radians(lat2)) * cos(radians(lon2) - radians(lon1)) + sin(radians(lat1)) * sin(radians(lat2)))

...然后像这样使用 UPDATE 查询

UPDATE `source` SET `source`.`sitecode` = (
    SELECT `sitecode` FROM `siteinfo`
    ORDER BY great_circle_km(`source`.`longitude`, `source`.`latitude`, `siteinfo`.`longitude`, `siteinfo`.`latitude`)
    LIMIT 1
    )

请注意,上述查询将执行相当于 CROSS JOIN(笛卡尔积)的操作,因此对于较大的源表,处理的有效行数将显着增加。例如,使用两个 500 行的表将有效处理 250,000 行,而使用两个 5,000 行的表将有效处理 25,000,000 行。

如果表之间可能存在大量精确匹配,那么首先更新它们可能会更快...

UPDATE 
    `source` 
    INNER JOIN 
    `siteinfo` 
        ON `source`.`longitude` = `siteinfo`.`longitude` 
            AND `source`.`latitude` = `siteinfo`.`latitude`
SET `source`.`sitecode` = `siteinfo`.`sitecode`

...然后更新剩余的行

UPDATE `source` SET `source`.`sitecode` = (
    SELECT `sitecode` FROM `siteinfo`
    ORDER BY great_circle_km(`source`.`longitude`, `source`.`latitude`, `siteinfo`.`longitude`, `siteinfo`.`latitude`)
    LIMIT 1
    )
WHERE `source`.`sitecode` IS NULL

【讨论】:

  • 工作完美,效率更高!
  • 对了,我发现分析较大的表(5000行)需要相当长的时间(大约2分钟),有什么提高时间效率的建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多