【问题标题】:MariaDB no equivalent function for ST_Distance_SphereMariaDB 没有 ST_Distance_Sphere 的等效函数
【发布时间】:2020-04-09 18:12:47
【问题描述】:

在 MySQL 5.7 中有一个名为 ST_Distance_Sphere 的函数,可用于查找半径内的点,例如:

CREATE TABLE `places` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) DEFAULT NULL,
  `coordinates` point DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `places` ( `name`, `coordinates`)
VALUES ("Eiffel Tower", POINT(48.858271, 2.293795));

INSERT INTO `places` ( `name`, `coordinates`)
VALUES ("Pere Lachaise", POINT(48.861131, 2.394683));

INSERT INTO `places` ( `name`, `coordinates`)
VALUES ("Brooklyn", POINT(40.711089, -73.948391));

如果我们想查看距离巴黎市中心卢浮宫不到 10 公里的所有点,我们可以这样做:

SELECT name FROM places
WHERE ST_Distance_Sphere(coordinates, POINT(48.861105, 2.335337)) < 10000

但 MariaDB 10.1+ 不支持此类功能

如何在 MariaDB 中重新创建相同的函数或重新创建相同的查询。以下帖子显示了一种重新创建相同函数FUNCTION ST_Distance_Sphere does not exist in MariaDB?

的方法

也许是这样的?

SELECT name FROM places
WHERE ST_Within(
   coordinates, ST_Buffer(POINT(48.861105, 2.335337), 10000)
);

任何帮助表示赞赏。

【问题讨论】:

  • 观看次数第二多的问题和投票第二高的MDEV-13467。大声抱怨。
  • @danblack 以下帖子中显示的功能是否正确? stackoverflow.com/questions/44409012/…
  • @danblack 我需要一个临时解决方案,因为该功能请求需要很长时间,然后必须等到托管服务提供商提供新的数据库版本。
  • 我其实不知道。我会使用dbfiddle.uk/?rdbms=mysql_8.0 与一些MySQL 进行核对。理解迫切的需要。向您的服务提供商或 MariaDB 请求改进的少量时间是对提高软件可维护性的投资。
  • 对 MariaDB 的定向捐赠可能会将jira.mariadb.org/browse/MDEV-13467 的优先级提高。

标签: mysql geometry mariadb geospatial


【解决方案1】:

我在http://mysql.rjweb.org/doc.php/find_nearest_in_mysql 中提供了一种解决方法——但是,它适用于latitudelongitude 的一对数字列,而不是POINTs。 (可以从POINT() 中提取。)

该链接的主要目的是您的“下一个”问题 - 如何加快按距离过滤的速度。它讨论了 5 种方法。 (您的代码仍然是性能最低的。)

【讨论】:

  • 以下操作似乎不如 st_distance_sphere 快:CREATE FUNCTION st_distance_sphere(pt1` POINT, pt2 POINT) RETURNS decimal(10,2) BEGIN return 6371000 * 2 * ASIN (SQRT(POWER(SIN((ST_Y(pt2) - ST_Y(pt1)) * pi()/180 / 2), 2) + COS(ST_Y(pt1) * pi()/180) * COS(ST_Y(pt2) ) * pi()/180) * POWER(SIN((ST_X(pt2) - ST_X(pt1)) * pi()/180 / 2), 2) )); END`
  • @adam78 - 建议使用DOUBLE 而不是DECIMAL。并查看RADIANS()
【解决方案2】:

基于@adam78 和@Rick James 的建议 我是这样解决的:

CREATE FUNCTION st_distance_sphere(pt1 POINT, pt2 POINT)
RETURNS double(10,2)

RETURN 6371000 * 2 * ASIN(
    SQRT(
        POWER(SIN((ST_Y(pt2) - ST_Y(pt1)) * pi()/180 / 2), 2) +
        COS(ST_Y(pt1) * pi()/180 ) *
        COS(ST_Y(pt2) * pi()/180) *
        POWER(SIN((ST_X(pt2) - ST_X(pt1)) * pi()/180 / 2), 2)
    )
)

【讨论】:

    【解决方案3】:

    我也遇到了同样的问题。 使用 ST_DISTANCE 链接:https://mariadb.com/kb/en/st_distance/ 简单例子:

    SELECT ST_DISTANCE(POINT(x y),POINT(x1 y1));
    

    返回坐标单位。

    【讨论】:

    • 请将代码 sn-ps 与链接一起添加到答案中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多