计算2个重复案例之间的地理距离
Posted
技术标签:
【中文标题】计算2个重复案例之间的地理距离【英文标题】:Calculate the geographic distance between 2 duplicated cases 【发布时间】:2021-11-20 13:40:31 【问题描述】:我正在尝试计算数据库中 2 个重复案例之间的距离 我正在研究 SQL Oracle
例如:
ID ID_Household long lat
1 1 3.2 22.2
1 2 2.3 21.2
2 3 22.2 45.4
2 4 12.8 15.9
3 3 11.2 13.2
3 4 11.2 13.2
我希望输出为
ID duplication_status distance
1 2 more than 100 meter
3 2 less than 100 meter
我尝试阅读大量文章和问题,但无法构建逻辑 How to calculate distance between multiple points in SQL Server?
【问题讨论】:
提示:聚合查询包含 HAVING 子句以及 WHERE 子句中的sdo_geom.sdo_distance
、sdo_geometry
和 sdo_point_type
函数。
你能打个例子吗?
你可以check out
要么使用sdo_geom.sdo_distance
(这是您必须付费购买的可选Oracle 功能),要么查看***.com/a/59171192/3027266
如果您对降低的准确性感到满意,您甚至可以使用简单的毕达哥拉斯:111km ⋅ sqrt((Δlat² + cos(lat) ⋅ Δlon²))
。这些是真正的价值吗? 0.1° 大约是 11 公里(在赤道处),因此任何大于 0.01 的原始差异肯定超过 100 米。
【参考方案1】:
您可以create the function:
CREATE FUNCTION haversine_distance(
lat1 IN NUMBER,
long1 IN NUMBER,
lat2 IN NUMBER,
long2 IN NUMBER
) RETURN NUMBER DETERMINISTIC
IS
PI CONSTANT NUMBER := ASIN(1) * 2;
R CONSTANT NUMBER := 6371000; -- Approx. radius of the earth in m
PHI1 CONSTANT NUMBER := lat1 * PI / 180;
PHI2 CONSTANT NUMBER := lat2 * PI / 180;
DELTA_PHI CONSTANT NUMBER := (lat2 - lat1) * PI / 180;
DELTA_LAMBDA CONSTANT NUMBER := (long2 - long1) * PI / 180;
a NUMBER;
c NUMBER;
BEGIN
a := SIN(delta_phi/2) * SIN(delta_phi/2) + COS(phi1) * COS(phi2) *
SIN(delta_lambda/2) * SIN(delta_lambda/2);
c := 2 * ATAN2(SQRT(a), SQRT(1-a));
RETURN R * c; -- in metres
END;
/
然后使用查询:
SELECT id,
haversine_distance(lat1, long1, lat2, long2) AS distance_metres,
CASE
WHEN haversine_distance(lat1, long1, lat2, long2) > 100
THEN 'more than 100 meter'
ELSE 'less than 100 meter'
END AS distance
FROM table_name
MATCH_RECOGNIZE(
PARTITION BY id
ORDER BY id_household
MEASURES
FIRST(longitude) AS long1,
FIRST(latitude) AS lat1,
LAST(longitude) AS long2,
LAST(latitude) AS lat2
PATTERN ( house2 )
DEFINE
house AS 1 = 1
);
或任何其他将行分组成对并旋转然后调用函数的方法。
其中,对于样本数据:
CREATE TABLE table_name (ID, ID_Household, longitude, latitude) AS
SELECT 1, 1, 3.2, 22.2 FROM DUAL UNION ALL
SELECT 1, 2, 2.3, 21.2 FROM DUAL UNION ALL
SELECT 2, 3, 22.2, 45.4 FROM DUAL UNION ALL
SELECT 2, 4, 12.8, 15.9 FROM DUAL UNION ALL
SELECT 3, 3, 11.2, 13.2 FROM DUAL UNION ALL
SELECT 3, 4, 11.2, 13.2 FROM DUAL;
输出:
ID DISTANCE_METRES DISTANCE 1 144947.804966182829942744055657720422603 more than 100 meter 2 3395725.11733156831056822390960787854383 more than 100 meter 3 0 less than 100 meter
或者,如果您想使用 SDO 几何函数:
SELECT id,
sdo_geom.sdo_distance(
sdo_geometry(
2001, -- 2D co-ordinate containing a single point
4326, -- Spatial reference system id (SRID) for WGS84 coordinates
sdo_point_type(lat1,long1,null),
null,
null
),
sdo_geometry(
2001, -- 2D co-ordinate containing a single point
4326, -- Spatial reference system id (SRID) for WGS84 coordinates
sdo_point_type(lat2,long2,null),
null,
null
),
0.005,
'unit=m'
) AS distance_metres,
CASE
WHEN sdo_geom.sdo_distance(
sdo_geometry(
2001, -- 2D co-ordinate containing a single point
4326, -- Spatial reference system id (SRID) for WGS84 coordinates
sdo_point_type(lat1,long1,null),
null,
null
),
sdo_geometry(
2001, -- 2D co-ordinate containing a single point
4326, -- Spatial reference system id (SRID) for WGS84 coordinates
sdo_point_type(lat2,long2,null),
null,
null
),
0.005,
'unit=m'
) > 100
THEN 'more than 100 meter'
ELSE 'less than 100 meter'
END AS distance
FROM table_name
MATCH_RECOGNIZE(
PARTITION BY id
ORDER BY id_household
MEASURES
FIRST(longitude) AS long1,
FIRST(latitude) AS lat1,
LAST(longitude) AS long2,
LAST(latitude) AS lat2
PATTERN ( house2 )
DEFINE
house AS 1 = 1
)
哪些输出:
ID DISTANCE_METRES DISTANCE 1 149223.001672844 more than 100 meter 2 3293714.72371264 more than 100 meter 3 0 less than 100 meter
db小提琴here
【讨论】:
以上是关于计算2个重复案例之间的地理距离的主要内容,如果未能解决你的问题,请参考以下文章