繁体   English   中英

如何从同一表的子查询中更新列?

[英]How to update a column from a subquery in the same table?

由于缓存的原因,我需要将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(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 Fiddle的链接http://sqlfiddle.com/#!9/7f95de/2/0

首先,不能保证您在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) 10,6)这样的decimal(10, 6)就足够了。

您可以设置函数以返回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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM