计算 2 个重复案例之间的地理距离

Calculate the geographic distance between 2 duplicated cases

我正在尝试计算数据库中 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?

你可以:

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<>fiddle here