在 Oracle 中查询半正弦公式

Posted

技术标签:

【中文标题】在 Oracle 中查询半正弦公式【英文标题】:Query for Haversine formula in Oracle 【发布时间】:2014-08-19 05:14:15 【问题描述】:

此查询运行良好,但我想在此查询中使用MIN 函数,因为我只想要一个与给定当前位置距离最短的站点。

如何在此查询中使用MIN

select *
from
(
  SELECT fc_station_mst.station_name,fc_station_mst.station_id,fc_station_mst.lat, fc_station_mst.longitude,fc_station_mst.state,
          fc_station_param_dtl.fc_date,fc_station_param_dtl.param_value,fc_parameter_mst.param_name,fc_parameter_mst.param_unit, 

  6371*(2*atan2 (sqrt(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) * 
  sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)+cos((3.14*fc_station_mst.lat)/180)*cos((3.14*23.07)/180) 
  * sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* 
  sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)),(sqrt(1-(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)
  *sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) +cos((3.14*fc_station_mst.lat)/180)* cos((3.14*23.07)/180)*
  sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)))))) as distance 

  FROM fc_station_mst, fc_station_param_dtl, fc_parameter_mst 

  where fc_station_param_dtl.param_id=fc_parameter_mst.param_id and
  fc_station_mst.station_id=fc_station_param_dtl.station_id  and  fc_station_param_dtl.param_id in(1,3,5,9)  and 
  fc_station_param_dtl.hourly_forecast='24' and fc_station_param_dtl.fc_date='22-JUL-2014'
) x

where   distance <= 15 ;

【问题讨论】:

GROUP BY 子句在哪里? 如果没有 GROUP BY 子句,则将 HAVING 子句作为单个组应用于整个结果 好的,但是我看,你在HAVING中使用了distance字段,但是这里不能用,因为它是min函数的别名,你必须要么添加*** select 并使用 where 子句,要么在 having 子句中使用带有 sin、sqrt 等的整个 min 函数。 select * from ( SELECT fc_station_mst.station_name,fc_station_mst.station_id,fc_station_mst.lat, fc_station_mst.longitude,fc_station_mst.state, fc_station_param_dtl.fc_date,fc_station_param_dtl.param_value,fc_parameter_mst.param_name,fc *(2*atan2 (sqrt(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) * sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)+ cos((3.14*fc_station_mst.lat)/180)*cos((3.14*23.07)/180) * sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2) ),(sqrt(1-(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) sin(((3.14*(fc_station_mst.lat-23.07))/180)/2 ) +cos((3.14*fc_station_mst.lat)/180) cos((3.14*23.07)/180)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)))))) 作为距离 fc_station_mst, fc_station_param_dtl, fc_parameter_mst 【参考方案1】:

首先你必须计算你拥有的所有距离,然后你得到最小距离并将它的值与所有距离进行比较。具有准确值的车站就是您的答案。像这样:

with t as (
    select * 
    from
    (
      SELECT 6371*(2*atan2 (sqrt(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) * 
              sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)+cos((3.14*fc_station_mst.lat)/180)*cos((3.14*23.07)/180) 
              * sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* 
              sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)),(sqrt(1-(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)
              *sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) +cos((3.14*fc_station_mst.lat)/180)* cos((3.14*23.07)/180)*
              sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)))))) as distance 
      FROM fc_station_mst, fc_station_param_dtl, fc_parameter_mst 

      where fc_station_param_dtl.param_id=fc_parameter_mst.param_id and
      fc_station_mst.station_id=fc_station_param_dtl.station_id  and  fc_station_param_dtl.param_id in(1,3,5,9)  and 
      fc_station_param_dtl.hourly_forecast='24' and fc_station_param_dtl.fc_date='22-JUL-2014'
    ) 
)
select fc_station_mst.station_name,fc_station_mst.station_id,fc_station_mst.lat, fc_station_mst.longitude,fc_station_mst.state,
       fc_station_param_dtl.fc_date,fc_station_param_dtl.param_value,fc_parameter_mst.param_name,fc_parameter_mst.param_unit
  from fc_station_mst, fc_station_param_dtl, fc_parameter_mst
     , (
        select min(distance) distance
          from t
       ) t1
 where t1.distance = 6371*(2*atan2 (sqrt(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) * 
      sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)+cos((3.14*fc_station_mst.lat)/180)*cos((3.14*23.07)/180) 
      * sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* 
      sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)),(sqrt(1-(sin(((3.14*(fc_station_mst.lat-23.07))/180)/2)
      *sin(((3.14*(fc_station_mst.lat-23.07))/180)/2) +cos((3.14*fc_station_mst.lat)/180)* cos((3.14*23.07)/180)*
      sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2)* sin(((3.14*(fc_station_mst.longitude-72.71))/180)/2))))))

【讨论】:

我必须首先找到从我当前位置到数据库中所有可用车站的距离,然后找到离我当前位置最近的车站的最小距离。如果这个距离小于 15,那么将是我的答案 你没有在回答中说出来,我怎么能猜到呢?下定决心,意识到你真正想要什么,然后在你的答案中表达出来。 请告诉我如何在此查询中使用 MIN 函数。我在 hasrsine 公式之前使用过,但它给了我“不是单组组函数”的错误,如果我从选择中删除了其他列并仅保留公式,然后它给了我距离...请帮助我进行此查询... 如果您仔细查看我的答案,您会看到:首先,我使用您的公式(WITH 部分)计算每个站点的距离,然后我计算我的值之间的最小距离之前计算,然后再次使用您的公式,我寻找具有精确值的值作为我之前计算的最小值的值。

以上是关于在 Oracle 中查询半正弦公式的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 子查询中使用多个表进行 Oracle 半联接

正弦公式 php / mysql

不使用三角函数的 SQL 距离查询

Have/Where 子句不适用于使用 Microsoft SQL 的 Haversine 公式

Oracle优化笔记

三角函数计算公式及查询表