在表1中找到Table2中每个位置的最近位置

时间:2017-09-21 10:18:55

标签: java mysql database jdbc

我目前使用的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表中的每一行,我想获取名为Longitude和Latitude的列,并将它们与siteinfo表中相应的Longitude和Latitude列进行比较。

源表中Long和Lat行与siteinfo表中的行最相似的那些行的sitecode列已更新为sitecode sitecode 1 {} siteinfo表中的列。

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

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

我想过做暴力,使用For循环比较说,Source Resultset的第一行条目与Siteinfo Resultset的每一行然后递增到第二行。

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

其次,如何找到两个结果表的列条目的差异?

1 个答案:

答案 0 :(得分:1)

不,您不必创建两个ResultSet。你可以创建一个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