您可以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 ( house{2} )
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 ( house{2} )
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