Mysql 如何从同一表中的子查询更新列?
出于缓存原因,我需要将Km字段写回位置表,到目前为止,我能够计算Km。到目前为止,我尝试使用联合、子查询等更新的所有内容都会导致SQL错误1093 在MySQL中,如何将Km值更新回表中 这是表模式Mysql 如何从同一表中的子查询更新列?,mysql,sql,Mysql,Sql,出于缓存原因,我需要将Km字段写回位置表,到目前为止,我能够计算Km。到目前为止,我尝试使用联合、子查询等更新的所有内容都会导致SQL错误1093 在MySQL中,如何将Km值更新回表中 这是表模式 CREATE TABLE `locations` ( `epoch_date` int(10) unsigned DEFAULT NULL, `latitude` float NOT NULL, `longitude` float NOT NULL, `km` float DEFAU
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);
这是生成公里数的select查询
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
这里有一个指向SQL FIDLE的链接首先,在select语句中使用变量不能保证有效。MySQL不保证select中表达式的顺序,因此变量可以按任意顺序分配。取决于评估的顺序是危险的 可能通过使用子查询解决该问题后,可以使用子查询更新km列:
update locations l join
(<your query here>) u
on l.latitude = u.latitude and l.longitude = u.longitude
set l.km = u.km;
哦,我还看到了其他危险的东西。您正在使用浮点数表示lat和long。您应该真正使用小数,通常情况下,小数10、6就足够了。您可以设置函数来返回上一个纬度和前一个经度,并在更新查询中使用它 像这样的
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 ;
可能重复的
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 ;
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);