【问题标题】:Ruby, SQLite and trigonometric functionsRuby、SQLite 和三角函数
【发布时间】:2011-08-15 23:16:08
【问题描述】:

我希望能够使用各种三角函数来使用 SQLite 数据库从 ruby​​ 中找到纬度和经度之间的距离。 SQLite 不提供三角函数(cossinpow)所以我正在寻找如何实现这些函数 - 有什么想法吗?

我知道我可以使用其他数据库(PostgreSQL、MySQL 等),但我需要使用 SQLite,因此不需要安装数据库。关于如何编译可以插入到 sqlite3 gem 中的 SQLite 扩展的任何想法?

谢谢!

【问题讨论】:

  • 您确定要在数据库级别而不是在 Ruby 中执行此操作吗?为什么?
  • @Henning 如果您有大量数据集或需要大量调用此函数(例如,使用大型数据集进行实时位置搜索、跑步旅行,则在 sqlite 级别使用 C 语言执行此操作会快几个数量级)计划算法、数据分析等)虽然在这些情况下,您通常会在 C/C++ 中实现整个事物,然后将其包装在 ruby​​ 中。我通常做的是近似距离以减少 sql 中的样本大小,然后在 ruby​​ 中运行距离计算。这假设您已将样本量减少到足够小。任何超过 500 点,速度差异就会变得明显。
  • @Charles:是的,但看起来 OP 正在寻求将其作为 SQL 表达式来执行,而不是 C 或 Ruby。如果 OP 计划将 C/C++ 用于球面距离,那么我不明白问题是什么。 C 确实有三角函数。
  • @Henning,OP 还询问了有关为 sqlite 编译扩展的问题,所以我认为这意味着自定义 sqlite 函数sqlite.org/capi3ref.html#sqlite3_create_function,然后将其包装成一个 ruby​​ 扩展,这是相当多的工作。
  • 我对我面临的问题的理解可能并不完整——我有一个语句可以在 MySQL 中使用sincosatan2pow 等(反hasrsine 公式),我想用它来按距离某个点的升序列出我的 SQLite 数据库的所有行。此表中的行数不可能超过几千行,但我想优化速度。

标签: ruby sqlite


【解决方案1】:

如果编写扩展的工作量太大,我通常针对这个问题所做的就是通过使用 lat/lng 边界框来近似我想要选择的距离(并高估一点),这会显着减少样本空间,然后在 ruby​​ 中迭代该集合以找到正确距离内的确切点集。

编辑:看起来有人已经编写了一个库,可以让您轻松定义函数,就好像它们是存储过程一样。我不知道它是否是一个 ruby​​ 实现,或者它是否会先将它编译成 C,所以我不知道性能,但它似乎很容易使用。 https://github.com/copiousfreetime/amalgalite

require 'rubygems'
$: << "../lib"
$: << "../ext"
require 'amalgalite'
db = Amalgalite::Database.new( "mydb.sqlite" )
db.define_function( 'geo_dist' ) do |lat1, lng1, lat2, lng2|
  # Haversine formular here to calculate the distance
end

这是完整的示例 https://github.com/copiousfreetime/amalgalite/blob/master/examples/define_function.rb

【讨论】:

  • 这看起来可能只是罚单 - 将调查!
  • 这个库绝对是完美的——但它不适用于最新版本的 Active Record! (Active Record 适配器也与早期版本的 Amalgalite 相关联)。我会尝试让它工作,但我对 ActiveRecord 内部的了解并不真正达到标准。
猜你喜欢
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多