ronald
5 سال پیش توسط ronald مطرح شد
3 پاسخ

محاسبه فاصله

سلام دوستان در sql روشی برای محاسبه فاصله با استفاده از lat , long و میشناسین
میخوام نزدیکترین ها به کاربر و از دیتا بیس بکشم بیرون .
البته این کار و با فانکشن بعد select داده ها میتونم انجام بدم .
اما برای بهینه تر کردن نیاز دارم که این محاسبه داخل query انجام بشه .
از دوستانی که تجربه این کار رو داشتن ممنون میشم اگر راهنمایی کنن.


ثبت پرسش جدید
رامین رضائی
تخصص : گرافیست سابق و برنامه نویس حال
@raminr77 5 سال پیش مطرح شد
1

سلام
شما میتونید برای اینکار از function ها ، stored procedure و یا trigger استفاده کنید.
اگر شما بعد از هر select روی جدول نیاز دارید این فاصله محاسبه بشه توصیه میشه از trigger استفاده کنید.
ولی اگر میخواهید فقط در زمانی که نیاز دارید این محاسبه انجام بشه میتونید از فانکشن استفاده کنید.

خیلی خوب هست که تصمیم گرفتید این محاسبه رو سمت DBMS انجام بدید !


محسن بستان
تخصص : Senior Backend Developer
@mohsenbostan 5 سال پیش مطرح شد
1

@crireal5
از لینک زیر برای درک الگوریتم محاسبه کمک بگیرید :
https://www.movable-type.co.uk/scripts/latlong.html
درمورد اینکه بخواید داخل کوئری کار رو انجام بدید، یک راه بهتر وجود داره و اونم متد chunk هستش که میتونید با استفاده از لینک زیر اون رو بررسی کنید:
https://laravel.com/docs/master/eloquent#chunking-results


coarad supp
تخصص : برنامه نویس لاراول
@coaradsupp 5 سال پیش آپدیت شد
1

سلام دوست عزیز

این تریت رو اضافه کن به مدلت

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

trait Geographical {

    /
      @param Builder $query
      @param float   $latitude Latitude
      @param float   $longitude Longitude

      @return Builder
     /
    public function scopeDistance( $query , $latitude , $longitude ) {
        $latName = $this->getQualifiedLatitudeColumn();
        $lonName = $this->getQualifiedLongitudeColumn();

        $query->select( ""
            , DB::raw("ROUND(6371  acos(cos(radians(" . $latitude . ")) 
         cos(radians(".$latName."))  cos(radians(".$lonName.") - radians(" . $longitude . ")) 
        + sin(radians(" .$latitude. ")) 
         sin(radians(".$latName."))),2) AS distance") );

        return $query;
    }

    public function scopeGeofence( $query , $latitude , $longitude , $inner_radius , $outer_radius ) {
        $query = $this->scopeDistance( $query , $latitude , $longitude );

        return $query->havingRaw( 'distance BETWEEN ? AND ?' , [ $inner_radius , $outer_radius ] );
    }

    public function scopeWhereDistance( $query , $operation , $distance ) {
        return $query->having('distance' ,$operation, $distance );
    }

    public function scopeWhereAround( $query , $inner_radius , $outer_radius ) {
        return $query->havingRaw( 'distance BETWEEN ? AND ?' , [ $inner_radius , $outer_radius ] );
    }

    public function scopeOrderByDistance( $query , $dir = 'ASC' ) {
        return $query->orderBy( 'distance' , $dir );
    }

    protected function getQualifiedLatitudeColumn() {
        return $this->getTable() . '.' . $this->getLatitudeColumn();
    }

    protected function getQualifiedLongitudeColumn() {
        return $this->getTable() . '.' . $this->getLongitudeColumn();
    }

    public function getLatitudeColumn() {
        return defined( 'static::LATITUDE' ) ? static::LATITUDE : 'latitude';
    }

    public function getLongitudeColumn() {
        return defined( 'static::LONGITUDE' ) ? static::LONGITUDE : 'longitude';
    }

}

به این شکل استفاده کن

if ( $request->lat && $request->long ) {
            $query->distance( $request->lat , $request->long );
        }
        if ( $request->distance ) {
            $query->whereDistance( '<' , $request->distance )->orderBy( 'distance' );
        }

برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام