For caching reasons I need to write the Km (kilometers) field back to the location table, so far I was able to calculate the Km. Everything I am trying so far (update with unions, subqueries, etc) gives me the SQL Error 1093.
In MySQL,how do I update the Km value back to the table?
This is the table schema
CREATE TABLE `locations` (
`epoch_date` int(10) unsigned DEFAULT NULL,
`latitude` float NOT NULL,
`longitude` float NOT NULL,
`km` float DEFAULT NULL
);
INSERT INTO `locations` (`epoch_date`, `latitude`, `longitude`, `km`) VALUES
(1429913506, -8.7285, 119.401, NULL),
(1429913631, -9.1279, 117.67, NULL),
(1429945707, -8.7063, 119.36, NULL),
(1431929523, -8.5745, 119.707, NULL),
(1431941343, -8.5773, 119.713, NULL),
(1431958383, -8.5881, 119.724, NULL),
(1431969963, -8.589, 119.728, NULL),
(1431998403, -8.5766, 119.724, NULL);
This is the select query that generates the KM (kilometer)
SELECT
latitude
, longitude
, epoch_date
, @latitude2 :=
(
SELECT
latitude
FROM locations loc1
WHERE
loc1.epoch_date < loc.epoch_date
ORDER BY epoch_date DESC LIMIT 1 OFFSET 0
) as prev_latitude
, @longitude2 :=
(
SELECT
longitude
FROM locations loc1
WHERE
loc1.epoch_date < loc.epoch_date
ORDER BY epoch_date DESC LIMIT 1 OFFSET 0
) as prev_longitude
, (ACOS(COS(RADIANS(90-latitude)) *COS(RADIANS(90-@latitude2)) +SIN(RADIANS(90-latitude)) *SIN(RADIANS(90-@latitude2)) *COS(RADIANS(longitude-@longitude2))) *6371) as km
FROM locations loc
ORDER BY epoch_date
Here is a link to the SQL Fiddle http://sqlfiddle.com/#!9/7f95de/2/0
First, your use of variables in the select
statement is not guaranteed to work. MySQL does not guarantee the ordering of expressions in a select
, so the variables could be assigned in any order. Depending on the order of evaluation is dangerous.
Once you solve that problem (probably by using a subquery), you can update the km
column by using a subquery:
update locations l join
(<your query here>) u
on l.latitude = u.latitude and l.longitude = u.longitude
set l.km = u.km;
Oh, I see something else dangerous as well. You are using floating point numbers for the representation of lat and long. You should really be using decimals, typically something like decimal(10, 6)
is sufficient for this purpose.
You could set up functions to return the prev_latitude and pre_longitude and use that in your UPDATE
query.
Something like this
DELIMITER $$
CREATE FUNCTION prev_latitude(epoch INT)
RETURNS FLOAT
LANGUAGE SQL
BEGIN
DECLARE lat FLOAT;
SET lat = null;
SELECT latitude INTO lat
FROM locations
WHERE epoch_date < epoch
ORDER BY epoch_date DESC LIMIT 1 OFFSET 0;
RETURN lat;
END;
$$
DELIMITER ;
And
DELIMITER $$
CREATE FUNCTION prev_longitude(epoch INT)
RETURNS FLOAT
LANGUAGE SQL
BEGIN
DECLARE lon FLOAT;
SET lon = null;
SELECT longitude INTO lon
FROM locations
WHERE epoch_date < epoch
ORDER BY epoch_date DESC LIMIT 1 OFFSET 0;
RETURN lon;
END;
$$
DELIMITER ;
And your update query can now be written as
UPDATE locations
SET km = (ACOS(COS(RADIANS(90-latitude)) *COS(RADIANS(90-prev_latitude(epoch_date))) +SIN(RADIANS(90-latitude)) *SIN(RADIANS(90-prev_latitude(epoch_date))) *COS(RADIANS(longitude-prev_longitude(epoch_date)))) *6371);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.