【问题标题】:Selecting Lat and Long based on circular range根据圆形范围选择纬度和经度
【发布时间】:2015-02-27 07:56:34
【问题描述】:

我正在构建一个应用程序来生成航空公司调度。从数据库中查询用户位置,输入他们想飞的最小距离和想飞的最大距离。我需要生成一个从始发机场到此范围之间的机场列表。我有一个计算距离的函数,但我只能先从数据库中提取所有机场数据才能使用它,这非常昂贵。有没有办法在 mySQL 代码中做到这一点。

谢谢, 戴夫

【问题讨论】:

    标签: php mysql geolocation latitude-longitude


    【解决方案1】:

    是的,我相信您可以在数据库中执行此操作。我使用类似的想法并在存储过程中运行代码 - 传入 lat/lng/radius 的参数。我认为下面的代码应该可以让您了解如何根据自己的需要实现它。

    begin
        declare strsql varchar(1000);
        declare dbrecords integer default 0;
        declare maxlimit integer default 0;
        declare lat double default 0;
        declare lng double default 0;
        declare radius float default 0;
        declare earth_radius integer default 0;
        declare lon1 float;
        declare lat1 float;
        declare lon2 float;
        declare lat2 float;
        set @lat=param_lat;
        set @lng=param_lng;
        set @radius=cast(param_radius as unsigned);
    
        set @earth_radius=3956;
        set @lon1 = @lng - @radius/ceil( cos( radians( @lat ) ) * 69 );
        set @lon2 = @lng + @radius/ceil( cos( radians( @lat ) ) * 69 );
        set @lat1 = @lat - ( @radius/69 );
        set @lat2 = @lat + ( @radius/69 );
        set @maxlimit=cast(param_limit as unsigned);
    
        set @strsql=concat("
        select distinct 
            m.`lat`,
            m.`lng`,
            m.`alt`,
            m.`region`,
            m.`unitaryautharea`,
            c.`council_name`,
            c.`normalised_title`,
            c.`council_lat`,
            c.`council_lng`,
            c.`cipfa_code`,
            c.`snac_id`,
            c.`wdtk_id`,
            c.`wdtk_name`,
            c.`egr_id`,
            c.`os_id`,
            c.`open_data_licence`
            w.`country_name`,
    
            /* This is the bit that does the main calculations and probably where you want to concentrate - the fields obviously will not relate to your db */
    
            truncate( @earth_radius * 2 * asin(sqrt( power( sin( (@lat - m.`lat`) * pi()/180 / 2), 2) +cos(@lat * pi()/180) * cos(m.`lat` * pi()/180) *power(sin((@lng - m.`lng`) * pi()/180 / 2), 2) ) ),3) as 'distance'
    
    
            from `metsitelist` m
            left outer join `ukcity_councils` c on c.`normalised_title`=m.`unitaryautharea`
            left outer join `ukcity_districts` d on d.`council_id`=c.`council_id`
            left outer join `ukcouncil_type` t on t.`id`=c.`council_authority_type_id`
            left outer join `ukcounties` ct on ct.`county_id`=c.`county_id`
            left outer join `worldcountries` w on w.`country_id`=c.`country_id`
            left outer join `metregions` r on r.`region`=m.`region`
    
            /* Here you find records within the range you want */
    
                where   (
                                ( m.`lat` between @lat1 and @lat2 ) 
                                and 
                                ( m.`lng` between @lon1 and @lon2 )
                        )
    
    
                /* ensure records are closer than max radius */ 
    
    
                having `distance` <= @radius 
                order by `distance`
                limit 0", @maxlimit ,";");
    
            prepare stmt from @strsql;
            execute stmt;
            deallocate prepare stmt;
    end
    

    希望你能利用这里的逻辑

    【讨论】:

    • 我的查询使用了平面世界坐标系 :) 干得好!我会分析你的计算,可能它们对我的postgrade工作有用。谢谢!
    • 我实际上可以理解其中的一些。谢谢!如果它解决了我的问题,我会告诉你的。给我几天时间。我在旁边做这些事情:-)
    【解决方案2】:

    大圆距离在http://mysql.rjweb.org/doc.php/latlng 中作为存储函数提供。

    【讨论】:

      【解决方案3】:

      嗯,您可以减少查询大小,但不能在数据库中计算整个任务(容易或不像 PHP 端那样轻量级)。此优化与 PHP 无关,仅与 MySQL (SQL) 相关,目标是大幅减少 PHP 端计算的元素数量。

      如果您有一个最大距离,那么您可以查询该范围内的所有机场并仅使用它们来计算最佳路线。

      SELECT * FROM (
          SELECT id, name, x, y,
              SQRT(POW(ABS(xpos - x), 2) + POW(ABS(ypos - y), 2)) distance 
              FROM table_name
      ) temp_table WHERE distance < max_distance
      

      它不会解决问题,但会有助于减少 PHP 方面的工作。

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-13
        • 2011-10-18
        • 1970-01-01
        • 2015-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多