我目前使用的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
表中相应的经度和纬度列进行比较。在源表中,长行和纬度行与
siteinfo
表中的行最相似的那些行,然后将sitecode
列更新为sitecode
表中sitecode
列的相应siteinfo
。例如,源表中的long和lat值与
siteinfo
表的第一行中的值最接近,因此sitecode
被更新为2。为了解决这个问题,我知道我必须创建两个ResultSet并使用while(next())遍历每个结果集的每一行。问题是,如何比较才能找到最相似的条目?
我考虑过使用蛮力,使用For循环将Source Resultset的第一行条目与Siteinfo Resultset的每一行进行比较,然后递增到第二行。
但是,我了解next()函数对每一行进行迭代的结果集工作,这与for循环不同,因为我想将一个结果集的第一行与另一结果集的每一行进行比较。
其次,如何找到两个结果表的列条目的区别?
最佳答案
不,您不必创建两个结果集。您可以只创建一个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