Tại sao bạn lại lưu trữ x, y trong các cột được phân tách? Tôi thực sự khuyên bạn nên lưu trữ chúng dưới dạng geometry
hoặc geography
để tránh chi phí truyền không cần thiết trong thời gian truy vấn.
Như đã nói, bạn có thể tính toán và kiểm tra khoảng cách theo dặm bằng cách sử dụng ST_DWithin
hoặc ST_Distance
:
(Dữ liệu thử nghiệm)
CREATE TABLE building (name text, long numeric, lat numeric);
INSERT INTO building VALUES ('Kirk Michael',-4.5896,54.2835);
INSERT INTO building VALUES ('Baldrine',-4.4077,54.2011);
INSERT INTO building VALUES ('Isle of Man Airport',-4.6283,54.0804);
ST_DWithin
ST_DWithin
trả về true nếu các hình đã cho nằm trong khoảng cách được chỉ định so với hình khác. Truy vấn sau tìm kiếm các hình trong bán kính 5 dặm từ POINT(-4.6314 54.0887)
:
SELECT name,long,lat,
ST_Distance('POINT(-4.6314 54.0887)'::geography,
ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE
ST_DWithin('POINT(-4.6314 54.0887)'::geography,
ST_MakePoint(long,lat),8046.72); -- 8046.72 metres = 5 miles;
name | long | lat | distance
---------------------+---------+---------+-------------------
Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)
ST_Distance
Hàm ST_Distance
(với geography
loại tham số) sẽ trả về khoảng cách tính bằng mét . Cuối cùng, khi sử dụng chức năng này, tất cả những gì bạn phải làm là chuyển đổi mét thành dặm.
Chú ý :Khoảng cách trong các truy vấn sử dụng ST_Distance
được tính trong thời gian thực và do đó không sử dụng chỉ mục không gian . Vì vậy, không nên sử dụng chức năng này trong WHERE
mệnh đề! Sử dụng nó thay vì trong SELECT
mệnh đề. Tuy nhiên, ví dụ dưới đây cho thấy cách nó có thể được thực hiện:
SELECT name,long,lat,
ST_Distance('POINT(-4.6314 54.0887)'::geography,
ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE
ST_Distance('POINT(-4.6314 54.0887)'::geography,
ST_MakePoint(long,lat)) * 0.000621371 <= 5;
name | long | lat | distance
---------------------+---------+---------+-------------------
Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)
- Lưu ý thứ tự các tham số với
ST_MakePoint
:Đó là kinh độ, vĩ độ .. không ngược lại.
Bản trình diễn:db<>fiddle
Tương đương với Amazon Athena (khoảng cách tính bằng độ):
SELECT *, ST_DISTANCE(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
ST_POINT(long,lat)) AS distance
FROM building
WHERE
ST_Distance(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
ST_POINT(long,lat)) <= 5;