gpt4 book ai didi

ios - Sqlite 中的 acos 函数

转载 作者:行者123 更新时间:2023-12-01 16:51:46 26 4
gpt4 key购买 nike

我有一个关于 SQLite 查询的问题。我需要执行这样的 sqlite 查询:

SELECT
id, (
6371 * acos (
cos ( radians(78.3232) )
* cos( radians( lat ) )
* cos( radians( lng ) - radians(65.3234) )
+ sin ( radians(78.3232) )
* sin( radians( lat ) )
)
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

但是我收到错误,因为 Sqlite 不支持像 acos 这样的函数。有没有办法在 Sqlite 中执行我的查询?我需要在 iOS 上使用这个。欢迎任何实用的建议。

最佳答案

您可以在 SQLite 中实现自己的函数。例如,为 acos 编写一个 SQLite C 函数包装器:

void sqlite_acos(sqlite3_context *context, int argc, sqlite3_value **argv)
{
int dataType = sqlite3_value_numeric_type(argv[0]);

if (dataType == SQLITE_INTEGER || dataType == SQLITE_FLOAT) {
double value = sqlite3_value_double(argv[0]);
sqlite3_result_double(context, acos(value));
} else {
sqlite3_result_null(context);
}
}

您可以对所需的每个三角函数重复此过程。

然后调用sqlite3_create_function将此C函数映射到SQL表达式:

- (BOOL)createFunctions:(sqlite3 *)db
{
int rc;

if ((rc = sqlite3_create_function(db, "acos", 1, SQLITE_ANY, NULL, sqlite_acos, NULL, NULL)) != SQLITE_OK) {
NSLog(@"%s: sqlite3_create_function acos error: %s (%d)", __FUNCTION__, sqlite3_errmsg(db), rc);
}

// repeat this for all of the other functions you define

return rc;
}
<小时/>

坦率地说,我不会编写这些单独的三角函数,而是编写一个进行更高级别距离计算的函数。这样效率会高一些。这可能看起来像:

double radians(double degrees)
{
return degrees * M_PI / 180.0;
}

void sqlite_distance(sqlite3_context *context, int argc, sqlite3_value **argv)
{
double values[4];

// get the double values for the four arguments

for (int i = 0; i < 4; i++) {
int dataType = sqlite3_value_numeric_type(argv[i]);

if (dataType == SQLITE_INTEGER || dataType == SQLITE_FLOAT) {
values[i] = sqlite3_value_double(argv[i]);
} else {
sqlite3_result_null(context);
return;
}
}

// let's give those values meaningful variable names

double lat = radians(values[0]);
double lng = radians(values[1]);
double lat2 = radians(values[2]);
double lng2 = radians(values[3]);

// calculate the distance

double result = 6371.0 * acos(cos(lat2) * cos(lat) * cos(lng - lng2) + sin(lat2) * sin(lat));

sqlite3_result_double(context, result);
}

然后您可以在 SQLite 中定义一个 distance 函数,如下所示:

int rc;

if ((rc = sqlite3_create_function(db, "distance", 4, SQLITE_ANY, NULL, sqlite_distance, NULL, NULL)) != SQLITE_OK) {
NSLog(@"%s: sqlite3_create_function distance error: %s (%d)", __FUNCTION__, sqlite3_errmsg(db), rc);
}

因此,您打开数据库,为这个 distance 函数调用 sqlite3_create_function,然后您可以编写使用这个新 distance 函数的 SQL :

const char *sql = "SELECT "
"id, distance(lat, lng, 65.3234, 78.3232) AS distance "
"FROM markers "
"WHERE distance < 30 "
"ORDER BY distance";

if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) != SQLITE_OK)
NSLog(@"prepare failed: %s", sqlite3_errmsg(db));

while (sqlite3_step(statement) == SQLITE_ROW) {
sqlite3_int64 rowid = sqlite3_column_int64(statement, 0);
double distance = sqlite3_column_double(statement, 1);
NSLog(@"%lld %f", rowid, distance);
}

sqlite3_finalize(statement);

distance函数在您关闭数据库之前一直有效,因此请确保每次打开数据库时都调用sqlite3_create_function

关于ios - Sqlite 中的 acos 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23612538/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com