【问题标题】:Searching a MySQL database for values serving the input lat/long在 MySQL 数据库中搜索服务于输入 lat/long 的值
【发布时间】:2020-08-05 03:49:12
【问题描述】:

这个问题不同于常规的 mysql lat/long,radius based data fetching

我想搜索一个包含以下列的mysql数据库表-

ID  Items   lat       long      serving_radius(in km)

1   Item1  26.120888  85.364723    2
2   Item2  26.120888  85.364723    5
3   Item3  25.859800  85.786598    4
4   Item4  26.594900  85.504799    8

现在,如果用户有 lat/long (29.941095/77.812424) 想知道哪些商品可以在他的位置提供。然后我将如何使用 php & mysql 获取结果。

【问题讨论】:

  • 请发布您的代码
  • 我使用以下代码获取预定义服务半径为 10 公里的结果
  • $query = mysqli_query($conn, "SELECT *, (6371 * acos(cos(radians('$lat')) * cos(radians(lat)) * cos( radians(lng) - 弧度('$long')) + sin(radians('$lat')) * sin(radians(lat)))) 作为产品的距离 WHERE status = '$status' HAVING distance
  • 但是现在我不知道如何在不同项目的服务半径不同时编写查询
  • 如果表很大,那么提到的直接解决方案会很慢。这是因为必须测试每一行。你最终会有多少行?

标签: php mysql geolocation latitude-longitude


【解决方案1】:

我猜你正在寻找的 SQL 是这个:

SELECT id, items, lat, long, serving_radius
FROM table 
WHERE lat = 29.941095 
AND long = 77.812424;

在您的 PHP 代码中,您应该使用 DB 驱动程序(我推荐您使用 PDO)来连接到 DB 并执行查询。

有很多关于如何使用 PDO(创建连接、选择、插入等)的教程。

我刚刚找到可以帮助你的教程:https://parzibyte.me/blog/en/2019/10/14/php-mysql-tutorial-using-pdo/

编辑:不确定您的意思是如何使用精确的 latlong 值或更接近它们的值构建查询。 有的话可以看看https://gis.stackexchange.com/questions/31628/find-points-within-a-distance-using-mysql

【讨论】:

    【解决方案2】:

    这个问题好像和MySQL - Find points within radius from database类似

    1. 在数据库中查找serving_radiuslat/lon 的半径。
    2. 使用函数MBRContains 查找包含用户点的多边形。
        SELECT
            *
        FROM 
            items
        WHERE
            MBRContains(
                GeomFromText('Polygon((0 0,0 100,100 100,100 0,0 0))'),
                GeomFromText('Point(77.812424 29.941095)')) = 1;
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      “serving_radius”是否已存储在您的表中? 你可以做的是获取距离并检查它是否在 serving_radius 下

      SELECT serving_radius, 
      (6371 * acos(cos(radians(" . $userLatitude . ")) * cos(radians(`latitude`)) * cos(radians(`longitude`) - radians(" . $userLongitude . ")) + sin(radians(" . $userLatitude . ")) * sin(radians(`latitude`)))) as distance 
      having distance < serving_radius
      

      【讨论】:

      • 是的,服务半径已经存储在表格中,不同项目可能不同
      • 您仍然需要检查每个项目的当前用户的距离,并根据位置或条件显示。
      • 你能回答这个问题吗? stackoverflow.com/questions/61286641/…
      • 警告:这总是涉及扫描整个表。
      【解决方案4】:

      由于半径是可变的,我认为您的问题比传统问题更棘手。

      请参阅http://mysql.rjweb.org/doc.php/find_nearest_in_mysql 进行讨论。

      这列出了“找到最近的 X”的 5 种方法。最简单但最慢的方法是检查每个项目的距离。由于使用“边界框”来限制需要检查的项目数量,因此其余所有操作都更快。但是,编码变得复杂。

      在您的情况下,边界框可能被限制为表中的最大半径。您的示例数据显示半径最大为 8,因此围绕起点构建一个边长为 2*8 的正方形可以让您了解我描述的各种技术。

      最简单的方法是INDEX(lat, lng), INDEX(lng, lat) 让优化器选择哪个更好。优点是它只检查 16 宽纬度(或经度)范围内的项目,而不是整个地球。缺点是对另一个方向的优化作用不大。

      我建议您使用该技术作为第一次剪辑。如果您需要更高的性能,请进一步阅读我的文档,最好再回来寻求更多帮助,

      那里讨论的技术还允许限制返回值的数量。

      【讨论】:

      • 亲爱的 Rick James,我访问了您的网站并阅读了该页面,但老实说,您的所有辛勤工作都让我印象深刻。您能否给我写一个适合我的解决方案。还请建议我应该用来实现它的表结构。表中的行数可以达到 100 万或更高,serving_radius 的值永远不会大于 10-15 公里。谢谢
      • @PranavKumar - 首先实现其他答案给出的SELECT。您的表结构可能很好,加上我在此答案中列出的两个索引。然后只关注我文章中的“边界框”解决方案(mysql.rjweb.org/doc.php/find_nearest_in_mysql#bounding_box)。忽略 Z 顺序和分区;它们很复杂。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多