根据圆形范围选择Lat和Long

时间:2015-02-27 07:56:35

标签: php mysql geolocation latitude-longitude

我正在构建一个生成航空公司调度的应用程序。从数据库中查询用户位置,他们输入他们想要飞行的最小距离以及他们想要飞行的最大距离。我需要生成一个机场列表,这些机场介于这个范围之间。我有一个计算距离的功能,但是如果我首先从数据库中提取所有机场数据,我只能使用它,这非常昂贵。有没有办法在mySQL代码中执行此操作。

谢谢, 戴夫

3 个答案:

答案 0 :(得分:1)

是的,我相信你可以在db中做到这一点。我使用类似的想法并在存储过程中运行代码 - 传入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

希望你能利用这里的逻辑

答案 1 :(得分:0)

嗯,您可以减少查询大小,但不能在数据库中计算整个任务(轻松或不像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方面的工作。

希望它有所帮助。

答案 2 :(得分:0)

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