Na jakiej zasadzie są zaprogramowane odległości miast

0

Mam takie pytanie czasami w ogłoszeniach o pracę są do wyboru, żeby szukać odległości w iluś tam km i moje pytanie jest takie jak to jest zaprogramowane, czy np. każde miasto ma swoje współrzędne X i Y ?

0

W najprostszej postaci właśnie tak. Pobierasz przez jakieś API współrzędne obu miast i obliczasz odległość z założeniem że ziemia jest kulą. W niektórych wypadkach możesz też użyć google api do wyliczenia drogi, ale to już chyba płatna opcja więc raczej do specjalnych zastosowań.

0
  1. Używasz np. Google Geocode JSON API do pobrania współrzędnych geograficznych tych miast, zapisujesz to w bazie
  2. Tutaj są przykłady zapytań SQL jeśli chodzi o obliczanie odległości

http://stackoverflow.com/questions/8599200/calculate-distance-given-2-points-latitude-and-longitude

0

A jak zapisać te dane współrzednych tych miast do bazy czy to działa na takiej zasadzie, że baza jest u mnie na serwerz czy baza jest globalna(google) ?

0

Ty masz tylko pobrać dane a co z nimi zrobisz potem to tylko twoja sprawa.

1

To nadal działa bez klucza????

https://maps.googleapis.com/maps/api/geocode/json?address=[ulica%2Bnr_domu],[kod_poczt%2Bmiasto],PL

Zwróci JSON a w nim dane: geometry -> location

lat i lng

i to są dane które należy zapisać w bazie i na bazie tego obliczać

2

Taki prosty przykład:

Tabela w MySQL:

CREATE TABLE  `locations` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `lat` float NOT NULL,
  `lng` float NOT NULL,
  `city` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Zaciąganie danych

<?php

$cities = array(
    'Lublin',
    'Warszawa',
    'Krakow',
    'Gdansk',
    'Poznan',
    'Zakopane',
    'Krasnystaw',
    'Zamosc',
);

$url = 'https://maps.googleapis.com/maps/api/geocode/json?address=%s,PL';
$dsn = 'mysql:host=localhost;dbname=test';
$db = new PDO($dsn, 'root', 'root');


foreach ($cities as $city)
{
    $json = file_get_contents(sprintf($url, $city));
    $location = json_decode($json)->results[0]->geometry->location;

    $stmt = $db->prepare('INSERT INTO locations (lat, lng, city) VALUES (:lat, :lng, :city)');
    $stmt->execute(array(
        ':lat' => $location->lat,
        ':lng' => $location->lng,
        ':city' => $city,
    ));

}

I pobieranie wszystkich miast w promieniu 250 km od Warszawy, z nią włącznie:

<?php

// Warszawa, pobrane wspolrzedne (np. z bazy)
// Pobieranie miast w promieniu 250 km od Warszawy
// z Warszawą włącznie
$lat = 52.2297;
$lng = 21.0122;
$distance = 250;

$dsn = 'mysql:host=localhost;dbname=test';
$db = new PDO($dsn, 'root', 'root');

$stmt = $db->prepare("SELECT city, (6371*acos(cos(radians(:lat)) * cos(radians(lat)) * cos(radians(lng)
 - radians(:lng)) + sin(radians(:lat)) * sin(radians(lat)))) AS distance FROM locations
 HAVING distance < :distance");

$stmt->execute(array(
    ':lng' => $lng,
    ':lat' => $lat,
    ':distance' => $distance,
));

echo '<pre>';
$rows = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($rows as $row)
{
    echo $row->city . "\n";
}
echo '</pre>';

Wynik:

Lublin
Warszawa
Krasnystaw
Zamosc
0

Teraz to zapytanie konkretnie to

    $long_km = DB::select("SELECT city, (6371*acos(cos(radians($x)) * cos(radians(x)) * cos(radians(y)
 - radians($y)) + sin(radians($x)) * sin(radians(x)))) AS distance FROM city
 HAVING distance < $km");

zwraca mi błąd

SQLSTATE[42000]: Syntax error or access violation: 1463 Non-grouping field 'distance' is used in HAVING clause (SQL: SELECT city, (6371*acos(cos(radians(51.2465)) * cos(radians(x)) * cos(radians(y)

  • radians(22.5684)) + sin(radians(51.2465)) * sin(radians(x)))) AS distance FROM city
    HAVING distance < 12)
0

Nie no ja przyjąłem że tabela nazywa się locations a nie city i taką też utworzyłem, tym masz tam city zamiast locations, podałem to w przykładzie i pewnie dlatego się wywala.

0

Tylko, że jemu chodzi a paramert distance.

0

Odziwo ten błąd pojawia się tylko w aplikacji laravel jak to zapytnie wklepię w konsolę to się nic nie pokaże.

0

Test na Laravelu 4.2, tabela o strukturze takiej jak podałem kilka postów wyżej,

class TestController extends Controller
{
    public function getCities()
    {
        $lat = 52.2297;
        $lng = 21.0122;
        $distance = 250;

        $result = DB::select("SELECT city, (6371 * acos(cos(radians($lat))"
        . "* cos(radians(lat)) * cos(radians(lng)"
        . " - radians($lng)) + sin(radians($lat)) * sin(radians(lat))))"
        . "AS distance FROM locations HAVING distance < $distance"
        );

        return '<pre>' . print_r($result, true) . '</pre>';
    }
}

wynik:

Array
(
    [0] => stdClass Object
        (
            [city] => Lublin
            [distance] => 153.08433974689
        )

    [1] => stdClass Object
        (
            [city] => Warszawa
            [distance] => 0.0033430168099889
        )

    [2] => stdClass Object
        (
            [city] => Krasnystaw
            [distance] => 203.52231607976
        )

    [3] => stdClass Object
        (
            [city] => Zamosc
            [distance] => 228.29220173039
        )
)
0

To jest na 100% przez to AS distance bo ja usunę to i to zostanie tak

SELECT city, (6371*acos(cos(radians($x)) * cos(radians(x)) * cos(radians(y)

  • radians($y)) + sin(radians($x)) * sin(radians(x)))) FROM city

To się dobrze wykonuje.

0

Dodam, że jak do innego zapytania wstawiłem as pole_tymczasowe i potem dałem w tym zapytaniu having pole_tymczasowe = 2 to też mi zwróciło taki sam błąd, a przez zwykłego sql jest poprawnie interpretowane

0

Nie wiem co to jest. To co tutaj podałem to poprawne zapytanie SQL, sprawdzałem działanie na Laravelu 4.2 i wcześniej PDO. Mam MySQL Server 5.4. Nie wiem w jakiej wersji masz MySQL i czy w ogóle korzystasz z MySQL a nie np. SQLite. Gorzej jeśli to problem wewnętrznie w Laravelu. Daj kod SQL (DDL) tej tabeli który masz w bazie. Nie wiem jakiego typu pola masz w tej tabeli.

0

Tabela city
id int(11) Nie Klucz główny NULL auto_increment
x float Tak Brak NULL
y float Tak Brak NULL
city varchar(100) Tak Brak NULL

Tabela work_offers

id int(10) unsigned Nie Klucz główny NULL auto_increment
name varchar(60) Nie Brak NULL
price int(11) Nie Brak NULL
date_add int(11) Nie Brak NULL
start_date date Nie Brak NULL
city varchar(90) Tak Brak NULL
education varchar(90) Nie Brak NULL
id_user int(11) Nie Brak NULL
remember_token varchar(100) Tak Brak NULL
created_at timestamp Tak Brak NULL
updated_at timestamp Tak Brak NULL
id_city int(11) Tak Brak NULL

0

Zmieniłem nazwę tabeli z locations na city

CREATE TABLE  `city` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `lat` float NOT NULL,
  `lng` float NOT NULL,
  `city` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

i skrypt:

<?php

$lat = 52.2297;
$lng = 21.0122;
$distance = 250;

$dsn = 'mysql:host=localhost;dbname=test';
$db = new PDO($dsn, 'root', 'root');

$stmt = $db->prepare("SELECT city, (6371*acos(cos(radians(:lat)) * cos(radians(lat)) * cos(radians(lng)
 - radians(:lng)) + sin(radians(:lat)) * sin(radians(lat)))) AS distance FROM city
 HAVING distance < :distance");

$stmt->execute(array(
    ':lng' => $lng,
    ':lat' => $lat,
    ':distance' => $distance,
));

echo '<pre>';
$rows = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($rows as $row)
{
    echo $row->city . "\n";
}
echo '</pre>';

I z tym też nie ma problemów, też wypluwa te miasta które są w odległości 250 km od Warszawy łącznie z nią. Nie mam pojęcia z czym się tak naprawdę wiąże Twój problem...

1

A zamiast tego having nie powinno być where? Nie ma tam nigdzie grupowania.

0

Może trzeba użyć innego sterownika do bazy mysql, a może po prostu trzeba coś zainportować to obsługi mysql np. use ? Bo to się dzieje przy każdej tabeli gdzie próbuje użyć operatora as i having.

A jakiej funkcji używasz w laravelu do drukwoania miast ?

4
 $stmt = $db->prepare("SELECT * FROM (SELECT city, (6371*acos(cos(radians(:lat)) * cos(radians(lat)) * cos(radians(lng)
 - radians(:lng)) + sin(radians(:lat)) * sin(radians(lat)))) AS distance FROM city) x
 WHERE distance < :distance");
0

Dzięki teraz działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1