根据圆形范围选择纬度和经度
Selecting Lat and Long based on circular range
我正在构建一个生成航空公司调度的应用程序。从数据库中查询用户位置,然后他们输入他们想要飞行的最小距离和他们想要飞行的最大距离。我需要生成一个机场列表,这些机场位于其始发机场的范围内。我有一个计算距离的函数,但我只有先从数据库中提取所有机场数据才能使用它,这非常昂贵。有没有办法在 mySQL 代码中做到这一点。
谢谢,
戴夫
嗯,你可以减少查询大小,但不能在数据库中计算整个任务(容易或不像 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 副业。
希望对您有所帮助。
是的,我相信你可以在数据库中做到这一点。我使用类似的想法和 运行 存储过程中的代码 - 为 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
希望你能利用这里的逻辑
大圆距离在 http://mysql.rjweb.org/doc.php/latlng 中作为存储函数可用。
我正在构建一个生成航空公司调度的应用程序。从数据库中查询用户位置,然后他们输入他们想要飞行的最小距离和他们想要飞行的最大距离。我需要生成一个机场列表,这些机场位于其始发机场的范围内。我有一个计算距离的函数,但我只有先从数据库中提取所有机场数据才能使用它,这非常昂贵。有没有办法在 mySQL 代码中做到这一点。
谢谢, 戴夫
嗯,你可以减少查询大小,但不能在数据库中计算整个任务(容易或不像 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 副业。
希望对您有所帮助。
是的,我相信你可以在数据库中做到这一点。我使用类似的想法和 运行 存储过程中的代码 - 为 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
希望你能利用这里的逻辑
大圆距离在 http://mysql.rjweb.org/doc.php/latlng 中作为存储函数可用。