2016-06-08 73 views
2

为了缓存的原因,我需要将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 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); 

这是产生KM(公里)

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([email protected])) +SIN(RADIANS(90-latitude)) *SIN(RADIANS([email protected])) *COS(RADIANS([email protected]))) *6371) as km 
FROM locations loc 
ORDER BY epoch_date 

下面是对SQL小提琴http://sqlfiddle.com/#!9/7f95de/2/0

+0

的[MySQL错误1093可能的复制 - 无法指定目标表在FROM子句中更新](http://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-upd吃入-从子句) – Solarflare

回答

3

首先链接选择查询,您在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。你应该真的使用小数,通常类似decimal(10, 6)就足够了这个目的。

1

您可以设置函数来返回prev_latitude和pre_longitude,并在您的UPDATE查询中使用该函数。

像这样的事情

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); 
相关问题