看起来 Express C 有一个包含空间处理的扩展。我从未使用过它(目前似乎无法访问),所以我无法与它交谈。我假设您想使用它(查找半径内的所有位置是一个非常标准的查询)。
如果由于某种原因您不能使用扩展程序,我会这样做:
保持表格原样,或者使用浮点数据类型,尽管请使用完整的属性名称(没有理由截断它们)。对于简单的需求,“位置”的名称可以存储在表中,但如果不止一件东西在同一个位置,您可能希望给它一个数字 ID(因此实际点只有一次)。
您还需要涵盖纬度和经度的索引(可能单向一个,或每列一个)。
然后,给定一个起始位置和距离,使用这个查询:
SELECT name, latitude, longitude
FROM location
WHERE (latitude >= :currentLatitude - :distance
AND latitude <= :currentLatitude + :distance)
AND (longitude >= :currentLongitude - :distance
AND longitude <= :currentLongitude + :distance)
-- The previous four lines reduce the points selected to a box.
-- This is, or course, not completely correct, but should allow
-- the query to use the indicies to greatly reduce the initial
-- set of points evaluated.
-- You may wish to flip the condition and use ABS(), but
-- I don't think that would use the index...
AND POWER(latitude - :currentLatitude, 2) + POWER(longitude - :currentLongitude, 2)
<= POWER (:distance, 2)
-- This uses the pythagorean theorem to find all points within the specified
-- distance. This works best if the points have been pre-limited in some
-- way, because an index would almost certainly not be used otherwise.
-- Note that, on a spherical surface, this isn't completely accurate
-- - namely, distances between longitude points get shorter the farther
-- from the equator the latitude is -
-- but for your purposes is likely to be fine.
编辑:
找到this after searching for 2 seconds on google,这也提醒我:distance 的单位是错误的。修改后的查询是:
WITH Nearby (name, latitude, longitude, dist) as (
SELECT name, latitdude, longitude,
ACOS(SIN(RADIANS(latitude)) * SIN(RADIANS(:currentLatitude)) +
COS(RADIANS(latitude)) * COS(RADIANS(:currentLatitude)) *
COS(RADIANS(:currentLongitude - longitude))) * :RADIUS_OF_EARTH as dist
FROM location
WHERE (latitude >= :currentLatitude - DEGREES(:distance / :RADIUS_OF_EARTH)
AND latitude <= :currentLatitude + DEGREES(:distance / :RADIUS_OF_EARTH))
AND (longitude >= :currentLongitude -
DEGREES(:distance / :RADIUS_OF_EARTH / COS(RADIANS(:currentLatitude)))
AND longitude <= :currentLongitude +
DEGREES(:distance / :RADIUS_OF_EARTH / COS(RADIANS(:currentLatitude))))
)
SELECT *
FROM Nearby
WHERE dist <= :distance
请注意,将距离函数包装在标记为 DETERMINISTIC 的 UDF 中将允许将其放置在 SELECT 和 HAVING 部分中,但实际上只调用一次,从而消除需要 CTE。