【问题标题】:Haversine query into OracleHaversine 查询到 Oracle
【发布时间】:2011-09-14 15:29:57
【问题描述】:

我目前必须检查我的查询并将它们转移到使用 Oracle 而不是 SQLSERVER 并且我有点卡住这个查询,我正在使用来自 here 的查询

SELECT TOP 1 * FROM ( SELECT o.outcode AS lead_postcode, v.location, 
v.location_name, v.outcode AS venue_postcode, 6371.0E * 
( 2.0E *asin(case when 1.0E < (sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-
(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT))) 
* cos(RADIANS(CAST(o.lat AS FLOAT))) * square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-
(RADIANS(CAST(v.lng AS FLOAT))))/2.0E))))) then 1.0E else 
(sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))
/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT)))
* square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng AS FLOAT))))
/2.0E))))) end )) AS distance FROM venue_postcodes v, uk_postcodes o 
WHERE o.outcode = @nrpostcode ) i WHERE distance<100 ORDER BY distance

现在我知道这是一个可怕的查询,但 Oracle 似乎遇到了很多问题。

首先它不喜欢6371E 中的E 和所有后续的E

其次,它不喜欢square 函数,所以我决定使用power 函数,但这仍然给了我错误。

第三,它不喜欢radians 函数

第四,它不喜欢 TOP 1 部分,所以我将其更改为在 WHERE 子句中使用 ROWNUM

我完全不知道在这里做什么。

关于我可以做些什么来使它工作的任何想法?

提前致谢

【问题讨论】:

  • horrible 转置为decent。使用空格。分成几部分(也许是功能)。分别尝试每个功能 - 并为 Oracle 找到等效功能。分别尝试每个子句(如 Top) - 并找到 Oracle 的等效子句。
  • 我似乎无法找到radians 的替代品,也无法弄清楚为什么会出现E 问题?网络上似乎没有太多关于 hasrsine 和 oracle 的内容
  • 我认为,如果您想“正确地”执行此操作,您最好使用 Oracle 的 Spatial 扩展名并使用它的一个距离函数(我认为包括 Haversine)来存储您的位置。但恐怕我不是甲骨文专家。否则,删除那些“E”;它们不是必需的,并开始告诉我们您针对每个问题收到的确切错误消息。
  • @Matt Gibson - 我已经放弃了E,我现在收到的错误是RADIANS - invalid identifier
  • 哦,至于弧度,请记住一个圆中有 2π 弧度,所以我认为您只需将度数除以大约 57.3 :) 但我个人会存储当我添加它们时,数据库中的纬度和经度也以弧度表示,以使这更容易和更快......

标签: sql sql-server oracle haversine


【解决方案1】:

我建议您采用稍微不同的方法。

查看此网站:http://psoug.org/reference/functions.html

查找引用“计算距离”的部分

【讨论】:

  • 我已经在我的代码中实现了它,它很有魅力 - 谢谢:)
  • @Jamie:这很好,解决了将代码转移到 Oracle 的直接问题。当您尝试在大表中使用 WHERE distance&lt;100 ORDER BY distance 进行任何查询时,必须为您的两个 (venue_postcodes, uk_postcodes) 表的每个行组合计算该函数。正如@Matt Gibson 所建议的那样,如果您希望性能更快,则应该对中型到大型表使用 Oracle 空间扩展。
  • 这是一个仅链接的答案,链接(当前)似乎已失效。
【解决方案2】:

我知道如何在 SQL Server 中执行此操作,这应该很容易移植到 Oracle:

这是我创建的一个 UDF,用于使用 Haversine 公式获得两个邮政编码之间的近似 crows flight 距离:

ALTER FUNCTION [dbo].[fn_GetZipDistanceMiles](
    @ZipFrom VARCHAR(20),
    @ZipTo VARCHAR(20)
)
RETURNS FLOAT 
AS  
BEGIN 

    DECLARE @Latitude1 FLOAT
    DECLARE @Longitude1 FLOAT
    DECLARE @Latitude2 FLOAT
    DECLARE @Longitude2 FLOAT

    SELECT  @Latitude1 = Latitude,
            @Longitude1 = Longitude
    FROM    ZipCode
    WHERE   ZipCode = @ZipFrom


    SELECT  @Latitude2 = Latitude,
            @Longitude2 = Longitude
    FROM    ZipCode
    WHERE   ZipCode = @ZipTo

    -- CONSTANTS
    DECLARE @EarthRadiusInMiles FLOAT
    SET @EarthRadiusInMiles = 3963.1

    -- RADIANS conversion
    DECLARE @Lat1Radians FLOAT
    DECLARE @Long1Radians FLOAT
    DECLARE @Lat2Radians FLOAT
    DECLARE @Long2Radians FLOAT

    SET @Lat1Radians = @Latitude1 * PI() / 180
    SET @Long1Radians = @Longitude1 * PI() / 180
    SET @Lat2Radians = @Latitude2 * PI() / 180
    SET @Long2Radians = @Longitude2 * PI() / 180

    RETURN ACOS(COS(@Lat1Radians) * COS(@Long1Radians) * COS(@Lat2Radians) * COS(@Long2Radians) + COS(@Lat1Radians) * SIN(@Long1Radians) * COS(@Lat2Radians) * SIN(@Long2Radians) + SIN(@Lat1Radians) * SIN(@Lat2Radians)) * @EarthRadiusInMiles

END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多