【问题标题】:How to get Distance in KM in this query如何在此查询中以 KM 为单位获取距离
【发布时间】:2018-10-06 22:30:16
【问题描述】:
$salons = Salon::select('salons.*')
    ->selectRaw('( 6371* acos( cos( radians(?) ) *
                   cos( radians( lat ) )
                   * cos( radians( lng ) - radians(?)
                   ) + sin( radians(?) ) *
                   sin( radians( lat ) ) )
                 ) AS distance', [$lat, $lng, $lat])
    ->havingRaw("distance < 25")
    ->where("category_Id" , "=" , $id)
    ->get();

这个查询给了我这个-

"distance": 0.05205731665026305, I want distance like this 1.2KM

我尝试但没有找到解决方案

【问题讨论】:

  • 您需要更好地解释您的问题和查询
  • 您可以在查询中包含concat,因此您无需循环并更改结果
  • 在球面几何中,将距离作为角度是远远不够的。想象一下位于赤道上且相隔 1 度的两点之间的距离,而靠近北极的两点也相隔 1 度(约 120 公里对几米)。

标签: php mysql sql laravel orm


【解决方案1】:

要获得km,您应该使用111.045 km 每度数(作为近似值)

   ( 111.045 * acos( cos( radians(?) ) *
                       cos( radians( lat ) )
                       * cos( radians( lng ) - radians(?)
                       ) + sin( radians(?) ) *
                       sin( radians( lat ) ) )
                     )

【讨论】:

    【解决方案2】:

    试试下面的查询

    $data = DB::table('salons AS S')
                    ->selectRaw("
                            ( FLOOR(6371 * ACOS( COS( RADIANS( '$lat' ) ) * COS( RADIANS( S.lat ) ) * COS( RADIANS( S.lng ) - RADIANS( '$lng' ) ) + SIN( RADIANS( '$lat' ) ) * SIN( RADIANS( S.lat ) ) )) ) distance")
                    ->havingRaw("distance < 25")
                    ->where("category_Id" , "=" , $id)
                    ->get();
    

    $lat, $lng 是变量。

    【讨论】:

      【解决方案3】:

      更好的方法是使用 PHP。 SQL 计算成本很高。在某些原始计数中,差异可能是 30 秒与 0.04 秒;)

      public function scopeDistance($query, $from_latitude, $from_longitude, $distance)
          {
              $between_coords = \App\Services\PlaceServices::calcCoordinates($from_longitude, $from_latitude, $distance);
      
              return $query
                  ->where(function ($q) use ($between_coords) {
                      $q->whereBetween('places.longitude', [$between_coords['min']['lng'], $between_coords['max']['lng']]);
                  })
                  ->where(function ($q) use ($between_coords) {
                      $q->whereBetween('places.latitude', [$between_coords['min']['lat'], $between_coords['max']['lat']]);
                  });
          }
      

      和 calcCoodinates()

      public static function calcCoordinates($longitude, $latitude, $radius = 20)
          {
              $lng_min = $longitude - $radius / abs(cos(deg2rad($latitude)) * 69);
              $lng_max = $longitude + $radius / abs(cos(deg2rad($latitude)) * 69);
              $lat_min = $latitude - ($radius / 69);
              $lat_max = $latitude + ($radius / 69);
      
              return [
                  'min' => [
                      'lat' => $lat_min,
                      'lng' => $lng_min,
                  ],
                  'max' => [
                      'lat' => $lat_max,
                      'lng' => $lng_max,
                  ],
              ];
          }
      

      那就用YourModel::distance($lat, $lon, $km)-&gt;get()

      【讨论】:

      • 这是圆的距离吗?还是正方形?例如lat lng min max 让人觉得它不是圆的,因为你只有 2 分
      • 它是方形的。我认为这是更好的性能的小代价
      猜你喜欢
      • 2015-10-19
      • 1970-01-01
      • 2020-08-26
      • 2021-01-09
      • 2011-08-10
      • 2012-07-01
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多