Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Truy vấn SQL cho tổng số điểm trong bán kính của một vị trí

MySQL Guru hay không, vấn đề là trừ khi bạn tìm ra cách lọc ra các hàng khác nhau, khoảng cách cần được tính toán giữa mỗi điểm và mỗi thành phố ...

Có hai cách tiếp cận chung có thể giúp ích cho tình hình

  • làm cho công thức khoảng cách đơn giản hơn
  • lọc ra các ứng cử viên không có khả năng trong bán kính 100 nghìn từ một thành phố nhất định

Trước khi đi vào hai con đường cải tiến này, bạn nên quyết định mức độ chính xác mong muốn đối với khoảng cách 100 dặm này, bạn cũng nên cho biết khu vực địa lý nào được cơ sở dữ liệu bao phủ (đây chỉ là lục địa Hoa Kỳ, v.v.

Lý do cho điều này là trong khi chính xác hơn về mặt số học, công thức Vòng tròn lớn, rất tốn kém về mặt tính toán. Một cách khác để cải thiện hiệu suất sẽ là lưu trữ "Tọa độ lưới" của các loại trong việc bổ sung (hoặc thay vì) tọa độ Vĩ độ / Kinh độ.

Chỉnh sửa :
Một vài ý tưởng về công thức đơn giản hơn (nhưng kém chính xác hơn) :
Vì chúng ta đang xử lý các khoảng cách tương đối nhỏ (và tôi đoán là từ 30 đến 48 độ Vĩ Bắc), chúng ta có thể sử dụng khoảng cách euclide (hoặc tốt hơn là bình phương của khoảng cách euclid) thay vì các công thức lượng giác hình cầu phức tạp hơn.
tùy thuộc vào mức độ chính xác dự kiến, thậm chí có thể chấp nhận được một tham số duy nhất cho khoảng cách tuyến tính đối với một mức độ kinh độ đầy đủ, lấy giá trị trung bình trên diện tích được xem xét (ví dụ khoảng 46 quy chế dặm). Công thức sau đó sẽ trở thành

  LatDegInMi = 69.0
  LongDegInMi = 46.0
  DistSquared = ((Lat1 - Lat2) * LatDegInMi) ^2 + ((Long1 - Long2) * LongDegInMi) ^2

Ý tưởng về một cột có thông tin lưới cần lọc để giới hạn số hàng được xem xét để tính toán khoảng cách.
Mỗi "điểm" trong hệ thống, có thể là thành phố, hoặc một điểm khác (? địa điểm giao hàng, địa điểm cửa hàng ... bất cứ điều gì) được gán hai tọa độ số nguyên xác định bình phương 25 dặm * 25 dặm nơi điểm nằm. Tọa độ của bất kỳ điểm nào trong vòng 100 dặm tính từ điểm tham chiếu (một thành phố nhất định), tối đa sẽ là +/- 4 theo hướng x và +/- 4 theo hướng y. Sau đó, chúng tôi có thể viết một truy vấn tương tự như sau

SELECT city, state, latitude, longitude, COUNT(*)
FROM zipcodes Z
JOIN points P 
  ON P.GridX IN (
    SELECT GridX - 4, GridX - 3, GridX - 2, GridX - 1, GridX, GridX +1, GridX + 2 GridX + 3, GridX +4
   FROM zipcode ZX WHERE Z.id = ZX.id)
  AND
   P.GridY IN (
    SELECT GridY - 4, GridY - 3, GridY - 2, GridY - 1, GridY, GridY +1, GridY + 2 GridY + 3, GridY +4
   FROM zipcode ZY WHERE Z.id = ZY.id)
WHERE P.Status = A
   AND ((Z.latitude - P.latitude) * LatDegInMi) ^2 
      + ((Z.longitude - P.longitude) * LongDegInMi) ^2 < (100^2)
GROUP BY city,state,latitude,longitude;

Lưu ý rằng LongDegInMi có thể được mã hóa cứng (giống nhau cho tất cả các vị trí trong lục địa Hoa Kỳ) hoặc đến từ bản ghi tương ứng trong bảng mã zip. Tương tự, LatDegInMi có thể được mã hóa cứng (ít cần phải làm cho nó thay đổi, vì không giống như cái khác, nó tương đối cố định).

Lý do tại sao điều này nhanh hơn là đối với hầu hết các bản ghi trong sản phẩm cacte giữa bảng mã zip và bảng điểm, chúng tôi không tính toán khoảng cách. Chúng tôi loại bỏ chúng trên cơ sở giá trị chỉ mục (GridX và GridY).

Điều này đưa chúng ta đến câu hỏi về việc tạo ra các chỉ mục SQL nào. Chắc chắn, chúng ta có thể muốn:- GridX + GridY + Trạng thái (trên bảng điểm) - GridY + GridX + trạng thái (có thể) - Thành phố + Bang + vĩ độ + kinh độ + GridX + GridY trên bảng zipcodes

Một giải pháp thay thế cho lưới là "ràng buộc" các giới hạn của vĩ độ và kinh độ mà chúng tôi sẽ xem xét, dựa trên vĩ độ và kinh độ của một thành phố nhất định. tức là điều kiện JOIN trở thành một dải ô chứ không phải là IN:

JOIN points P 
  ON    P.latitude > (Z.Latitude - (100 / LatDegInMi)) 
    AND P.latitude < (Z.Latitude + (100 / LatDegInMi)) 
    AND P.longitude > (Z.longitude - (100 / LongDegInMi)) 
    AND P.longitude < (Z.longitude + (100 / LongDegInMi)) 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nếu mysql_num_rows bằng ZERO thì KHÔNG hoạt động

  2. Làm thế nào để chạy tập lệnh SQL trong MySQL?

  3. Ràng buộc MySQL InnoDB không hoạt động

  4. C # với MySQL - Lỗi:Hướng dẫn phải chứa 32 chữ số với 4 dấu gạch ngang khi cố gắng mở kết nối

  5. Nhóm theo người dùng và hiển thị mới nhất trong MYSQL không hoạt động