2011-09-14 15 views
2

我目前不必經過我的查詢,並在轉讓他們使用的是Oracle,而不是SQLSERVER和我有點堅持這一查詢我是來自here半正矢查詢到Oracle

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似乎遇到了很多問題。

首先,它不喜歡6371EE和所有後續E

其次它不喜歡的square功能,所以我決定用power功能,但仍給了我的錯誤。

第三它不喜歡的radians功能

第四它不喜歡的TOP 1一部分,所以我改變了這個WHERE子句中使用ROWNUM

我完全失去了,以什麼在這裏做。

任何想法,我可以做些什麼來使它工作?

在此先感謝

+4

從'horrible'到'decent'移調。使用空格。分解成部分(也許是函數)。分別嘗試每個功能 - 並找到與Oracle相同的功能。分別嘗試每個子句(如'Top') - 並找到與Oracle相同的東西。 –

+1

我似乎無法找到'radians'的替代方法或找出爲什麼'E'問題正在發生?網上似乎沒有太多關於hadrsine和oracle的信息 –

+1

我認爲如果你想「正確地」這樣做,你最好用Oracle的[Spatial](http:// download)存儲你的位置.oracle.com/docs/html/A88805_01/sdo_intr.htm)擴展名和使用它的一個距離函數,我認爲它包括Haversine。但我恐怕不是Oracle專家。否則,放棄這些「E」;他們是不需要的,並開始告訴我們你得到的每個問題的確切錯誤信息。 –

回答

4

我建議你採取一個稍微不同的方法。

看看這個網站:http://psoug.org/reference/functions.html

查找部分提到 「計算距離」

+0

我在我的代碼中實現了這個功能,它的功能非常強大 - 謝謝:) –

+0

@Jamie:這很好,解決了將代碼轉移到Oracle的直接問題。當您在大表中嘗試使用'WHERE distance <100 ORDER BY distance'的任何查詢時,必須爲您的兩個'(venue_postcodes,uk_postcodes)'表的行的每個組合計算函數。正如@Matt Gibson所建議的那樣,如果您希望性能變得更快,您應該使用Oracle空間擴展來創建大到中等的表格。 –

0

我知道該怎麼做,在SQL Server中,這應該是很容易移植到甲骨文:

這是我創建得到近似的烏鴉飛行距離的UDF兩個郵政編碼之間使用Haversine公式:

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