Tìm điểm trong khoảng cách bằng MySQL


20

Tôi có một bảng myQuery với tên người dùng, vĩ độ và kinh độ của người dùng. Tôi muốn có một danh sách người dùng nằm trong vòng tròn hoặc hình vuông của một vĩ độ và kinh độ nhất định với khoảng cách nhất định. Ví dụ đầu vào của tôi Lạt = 78,3232 và Long = 65,3234 và khoảng cách = 30 dặm. Tôi muốn lấy danh sách người dùng đang ở trong 30 dặm khoảng cách từ điểm 78,3232 và 65,3234. Có thể giải quyết điều này với truy vấn duy nhất? Hoặc bạn có thể cho tôi một gợi ý bắt đầu giải quyết truy vấn này? Tôi mới biết thông tin dựa trên địa lý.


Tại sao không PostGIS? Nếu bạn đang bắt đầu dự án địa lý, bạn vẫn có thể thay đổi ngăn xếp của mình
Simplexio

stackoverflow.com/a/40272394/1281385 Sẽ hữu ích trong việc tăng tốc truy vấn này (nếu cần)
exussum

Câu trả lời:


32

Các câu lệnh SQL mà sẽ tìm ra 20 địa điểm gần nhất mà là trong vòng bán kính 30 dặm về phía 78,3232, 65,3234 phối hợp. Nó tính toán khoảng cách dựa trên các vĩ độ / kinh độ của hàng đó và các mục tiêu vĩ độ / kinh độ, và sau đó yêu cầu chỉ hàng trong đó giá trị khoảng cách ít hơn 30 dặm, đơn đặt hàng toàn bộ truy vấn theo khoảng cách, và giới hạn nó đến 20 kết quả. Để tìm kiếm theo km thay vì dặm, thay thế 3959 với 6371.

SELECT
  id, (
    3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
  ) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Điều này đang sử dụng Google Maps API v3 với phần phụ trợ MySQL mà bạn đã có.

https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql


Tôi đang gặp lỗi cú pháp trong lựa chọn của mình bằng cách sử dụng này, "# 1582 - Số tham số không chính xác trong lệnh gọi hàm gốc 'radian' nó có thể là gì?
bluantinoo

Tìm thấy: Tôi đã có biến lng trống! lấy làm tiếc!
bluantinoo

Chính xác những gì tôi muốn, nhưng hiệu năng truy vấn quá tải cho hàng ngàn bản ghi? và độ chính xác như thế nào?
Amit Shah

1
tốt hơn nhiều để thay thế nó thành 6371392.896 để tìm kiếm theo mét
Vasilii Suricov

34

Câu trả lời của Mapperz không hợp lệ. Xoang phải được tính từ vĩ độ và KHÔNG từ kinh độ. Vì vậy, câu lệnh SQL xác thực là:

SELECT
    id, (
      3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Câu trả lời của bạn nên được đặt hàng đầu tiên.
Amit Shah

@AmitShah Nếu bạn nghĩ rằng bạn có thể ping người hỏi (@shihabK, người đã không hoạt động trên trang web trong gần 6 năm) và / hoặc bỏ phiếu cho meta.stackexchange.com/questions/268666/
Thẻ

Đây phải là câu trả lời được chấp nhận.
catbadger

2

Nó có thể là cơ sở để tạo ra một chức năng .. vì vậy bạn có thể sử dụng lại các khu vực khác. Cũng sẽ làm cho truy vấn của bạn sạch hơn một chút ... Ít nhất đó là 2 xu của tôi.

DELIMITER $$

create function calcDistance(lat float, lng float, pnt_lat float, pnt_lng float)

Returns float
BEGIN

Declare dist float;
SET dist =
  3959 * acos (
  cos ( radians(pnt_lat) )
  * cos( radians( lat ) )
  * cos( radians( lng ) - radians(pnt_lng) )
  + sin ( radians(pnt_lat) )
  * sin( radians( lat ) )
);

RETURN dist;

END

Câu trả lời sẽ được nâng cao nếu bạn sửa chữa kiểu chữ. đúng cách
Vasilii Suricov

0

Đây là biến thể truy vấn của tôi, có vẻ dễ hơn một chút ( http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-USE-mysql )

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`

4
Nó dễ dàng hơn nhưng bỏ qua thực tế là trái đất bị cong.
Tim Rijavec

Cần một công thức để được chính xác. Có lẽ điều này chỉ tốt trên những khoảng cách ngắn: D
Jethro

Bạn sẽ phóng một tên lửa, hay cái gì đó?
Dennis Braga

1
@DennisBraga - nếu vậy, thì có lẽ câu hỏi này không có chủ đề, phù hợp hơn với http://globalthermonuclewar.stackexchange.com ...?
ashleedawg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.