Вот мой SQLFiddle и вот моя процедура
Я хочу переписать эту процедуру на простую операцию.
Он должен принимать входные данные как Lat, Lng и возвращать ближайший driverid, lat, long (Order by desc и брать первую запись) относительно заданных Lat и Long. Он содержит некоторые другие таблицы, которые мне не нужны.
(Проблема в том, что я не могу найти, какое поле является обязательным, а какое нет)
DELIMITER //
CREATE PROCEDURE `driver_latlong`(IN `lat` DECIMAL(20,9), IN `lng` DECIMAL(20,9))
BEGIN
SET @sql = CONCAT('SELECT sd.DriverId, sd.Lat, sd.Long, sd1.RadiusOfService, @dist:= ( 6371 * acos( cos( radians(',lat,') ) * cos( radians( sd.Lat ) ) * cos( radians( sd.Long ) - radians(',lng,') ) + sin( radians(',lat,') ) * sin( radians( sd.Lat ) ) ) ) AS distance
, Case When @dist <= 1 Then sd1.DeliveryFeeOne When @dist<= 2 Then sd1.DeliveryFeeTwo When @dist<= 3 Then sd1.DeliveryFeeThree Else sd1.DeliveryFeeMore End as deliveryfee
, Case When @dist <= 1 Then sd1.DeliveryTimeOne When @dist<= 2 Then sd1.DeliveryTimeTwo When @dist<= 3 Then sd1.DeliveryTimeThree Else sd1.DeliveryTimeMore End as deliverytime
, sd.ShopName, sd.Address, sd.LogoFile FROM driver_latlong sd LEFT JOIN WHERE sd.Status = \'1\' and sd.Lat != 0 and sd.Long != 0 AND ( 6371 * acos( cos( radians(',lat,') ) * cos( radians( sd.Lat ) ) * cos( radians( sd.Long ) - radians(',lng,') ) + sin( radians(',lat,') ) * sin( radians( sd.Lat ) ) ) ) <= sd1.RadiusOfService ORDER BY distance ASC;');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
Замечания : На самом деле я получил эту процедуру из предыдущего проекта, поэтому другие таблицы не требуются, только таблица, на которую мы ссылаемся, это driver_latlong
Спасибо
Я предполагаю, что вы не слишком заботитесь о кривизне Земли, поэтому я рассматриваю длинные и ширые как оси на квадратной сетке. Это делает расчет довольно простым, используя Пифагор.
DELIMITER //
CREATE PROCEDURE `getNearestDriver` (
IN `inLat` DECIMAL(20,9), IN `inLong` DECIMAL(20,9),
OUT `outDriverId` INT(11), OUT `outLat` FLOAT, OUT `outLong` FLOAT
)
BEGIN
SELECT
`DriverId`, `Lat`, `Long` INTO `outDriverId`, `outLat`, `outLong`
FROM `driver_latlong`
# If the difference in lat and long make up two sides of a
# right angled triangle then the hypotenuse is the distance.
ORDER BY ( POWER(`inLat` - `Lat`, 2) + POWER(`inLong` - `Long`, 2) )
LIMIT 1;
END//
DELIMITER ;
SET @myLat = 11;
SET @myLong = 77;
SET @DriverId = 0;
SET @DriverLat = 0;
SET @DriverLong = 0;
CALL getNearestDriver( @myLat, @myLong, @DriverId, @DriverLat, @DriverLong );
SELECT @DriverId, @DriverLat, @DriverLong;
DROP PROCEDURE `getNearestDriver`;
DROP TABLE `driver_latlong`;
Других решений пока нет …