NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Existuje možnost, jak vybrat nejbližší hodnotu ze dvou sloupců?

V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Zbyněk Chatt:3.1.2023 11:56

Potřeboval bych vytáhnout třeba 10 nejbližších lidí podle koordinátů, latitude a longtitude. Uložené ve dvou sloupcích. Je nějaká možnost, jak to udělat?

 
Odpovědět
3.1.2023 11:56
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:3.1.2023 15:25

Mozna je na to funkce.

Jak bys to udelal na ctvercove mape?
Spocital by sis odmocninu rozdilu souradnic, ne? A seradil to ASC podle toho cisla. To preci umi deti na zakladni skole.

A nebo, kdyz vis predem, ze tohle budes pouzivat casto, vytvorit si jakousi fiktivni ctvereckovou sit. Kde budes mit proste uz osoby naskatulkovane. Tazke kolem vybrane skatulky vytahnes 8 dalsich ctverecku a vse bud zobrazis nebo provedes presnejsi prepocet pres tu absolutni hodnotu. !00 vypoctu je porad mene nez pres celou databazi treba milion radku :)

| 4,4 | 5,4 | 6,4 |
| 4,5 | X,Y | 6,5 |
| 4,6 | 5,6 | 6,6 |

Stred ma pozici X, Y = 5,5
Okolni body 4,4 az 6,6
Vsechno to selektnes (coz je treba 100 osob) a provedes presnejsi prepocet gps.

 
Nahoru Odpovědět
3.1.2023 15:25
Avatar
Petan
Člen
Avatar
Petan:3.1.2023 19:11

Ahoj
nějak by se mělo byt vytvořit sql funkci Vzdalenost() a volat

SELECT TOP 10 Vzdalenost(lat,lot,50.0,18.0) as Vzdalenost,name,... FROM table ORDER BY Vzdalenost

a funkci mam v c, je nutno ji přepsat do požadovaného sql

double GetDistancGps(double Lat1,double Long1,double Lat2,double Long2)
{
    double dDistance = 0;
    double dLat1InRad = Lat1 * (PI / 180.0);
    double dLong1InRad = Long1 * (PI / 180.0);
    double dLat2InRad = Lat2 * (PI / 180.0);
    double dLong2InRad = Long2 * (PI / 180.0);

    double dLongitude = dLong2InRad - dLong1InRad;
    double dLatitude = dLat2InRad - dLat1InRad;

    double a = pow(sin(dLatitude / 2.0), 2.0) +
                cos(dLat1InRad) * cos(dLat2InRad) *
                pow(sin(dLongitude / 2.0), 2.0);

    double c = 2.0 * atan2(sqrt(a), sqrt(1.0 - a));

    const double kEarthRadiusKms = 6376.5;
    dDistance = kEarthRadiusKms * c;

    return dDistance;
}

funkce není moje, opsal jsem ji kdysi dávno z nějakého excelu

 
Nahoru Odpovědět
3.1.2023 19:11
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Zbyněk Chatt
DarkCoder:3.1.2023 21:56

Vzdálenost mezi dvěma body na kouli vzhledem k jejich zeměpisné délce a zeměpisné šířce lze určit pomocí Haversinova vzorce.

Funkce, kterou zde zveřejnil Petan, je správná. Pro úplnost zde je celý program v C pro výpočet vzdálenosti.

#include <stdio.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.141592653
#endif

#define EARTH_RADIUS 6371 // Prumerny zemsky polomer v kilometrech
#define DEG_TO_RAD(deg) ((deg) * M_PI / 180.0)

double haversine_distance(double lat1, double lon1, double lat2, double lon2);

int main(void) {
    // Vzdalenost mezi NewYorkem a Londynem v km
    printf("%f\n", haversine_distance(40.6892, -74.0444, 51.5074, -0.1278));
    return 0;
}

double haversine_distance(double lat1, double lon1, double lat2, double lon2){
    double lat_diff = DEG_TO_RAD(lat2 - lat1);
    double lon_diff = DEG_TO_RAD(lon2 - lon1);
    lat1 = DEG_TO_RAD(lat1);
    lat2 = DEG_TO_RAD(lat2);

    double a = sin(lat_diff / 2) * sin(lat_diff / 2) +
        cos(lat1) * cos(lat2) *
        sin(lon_diff / 2) * sin(lon_diff / 2);
    double c = 2 * atan2(sqrt(a), sqrt(1 - a));
    return EARTH_RADIUS * c;
}

Dále zde je program pro vyhledání 10 nejmenších čísel z pole:

#include <stdio.h>
#include <limits.h>

#define N_SMALLEST 10 // Pocet nejmensich hledanych cisel

int* get_smallest(int* arr, int len);

int main(void) {
    int arr[] = { 4, 2, 9, 7, 3, 6, 1, 8, 5, 0, 0, 2, 4, 9, 7, 1, 6, 4, 3, 2};
    int size = (int)(sizeof(arr) / sizeof(arr[0]));

    int* smallest = get_smallest(arr, size);

    for (size_t i = 0; i < N_SMALLEST; i++) {
        printf("%d ", smallest[i]);
    }

    return 0;
}

int* get_smallest(int* arr, int len){
    static int smallest[N_SMALLEST]; // Pole udrzujici nejmensi cisla

    // Inicializace pole nejvetsimi moznymi hodnotami
    for (int i = 0; i < N_SMALLEST; i++) {
        smallest[i] = INT_MAX;
    }

    // Hledani 10 nejmensich cisel
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < N_SMALLEST; j++) {
            if (arr[i] < smallest[j]) {
                // odsun nejvetsich cisel vpravo
                for (int k = N_SMALLEST - 1; k > j; k--) {
                    smallest[k] = smallest[k - 1];
                }
                smallest[j] = arr[i];
                break;
            }
        }
    }

    return smallest;
}

Určitě by stálo zauvažovat nad nějakou optimalizací pro počet lidí.

Nahoru Odpovědět
3.1.2023 21:56
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Zbyněk Chatt
Matúš Olejník:3.1.2023 22:34

Vyskúšaj toto https://chat.openai.com/chat :D

write sql to find 10 nearest people based on columns lattitude and longtitude

Assuming that you have a table named people with columns id, latitude, and longitude, you can use the following SQL query to find the 10 nearest people based on their latitude and longitude:

SELECT id, latitude, longitude,
       (6371 * ACOS(COS(RADIANS(@lat)) * COS(RADIANS(latitude)) * COS(RADIANS(longitude) - RADIANS(@lng)) + SIN(RADIANS(@lat)) * SIN(RADIANS(latitude)))) AS distance
FROM people
WHERE id <> @id
HAVING distance < @radius
ORDER BY distance ASC
LIMIT 10;

This query uses the Haversine formula to calculate the distance between two points on a sphere. The formula takes the latitude and longitude of the two points, and returns the distance in kilometers.
To use the query, you need to set the values of the following parameters:
@lat: the latitude of the reference point
@lng: the longitude of the reference point
@id: the ID of the reference person (to exclude the reference person from the results)
@radius: the maximum distance to search for nearby people (in kilometers)
Note that the Haversine formula is an approximation that assumes that the Earth is a perfect sphere. If you need a more accurate calculation, you can use a more complex formula that takes into account the Earth's elliptical shape.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
3.1.2023 22:34
/* I am not sure why this works but it fixes the problem */
Avatar
Petan
Člen
Avatar
Petan:4.1.2023 7:45

pokud je to na MSSQL tak jsou tam typy geography
a použít

SELECT top 10
       geography::Point([latitude],[longtitude], 4326).STDistance(geography::Point(49.7840275, 17.8136961, 4326)) as metry,
       ...
       FROM table
       ORDER BY 1
 
Nahoru Odpovědět
4.1.2023 7:45
Avatar
Odpovídá na Matúš Olejník
Zbyněk Chatt:5.1.2023 9:34

Že mě to nenapadlo hned, samozřejmě, používam to občas :D Tak to je perfektní. :)

 
Nahoru Odpovědět
5.1.2023 9:34
Avatar
Zbyněk Chatt:5.1.2023 9:37

Díky všem za snahu, příspěvek s použitelným kódem jsem označil. :) Ostatním díky, A DarkCoder, Tvůj kód prostuduju v rámci toho se něco přiučit, ale až tak složité to nepotřebuji, každopádně dík :)

 
Nahoru Odpovědět
5.1.2023 9:37
Avatar
Zbyněk Chatt:19.1.2023 14:07

Kdyby se někomu hodilo, přikládám finální kód.

SELECT
  courier_id, c.name,
  (
    6371 * acos (
      cos ( radians( (SELECT latitude FROM courier_coords WHERE courier_id = '$my_courier_id') ) )
      * cos( radians( latitude ) )
      * cos( radians( longtitude ) - radians( (SELECT longtitude FROM courier_coords WHERE courier_id = '$my_courier_id') ) )
      + sin ( radians( (SELECT latitude FROM courier_coords WHERE courier_id = '$my_courier_id') ) )
      * sin( radians( latitude ) )
    )
    ) AS distance

        FROM courier_coords
        LEFT JOIN (SELECT id AS id2, name FROM courier) c ON c.id2 = courier_id
        WHERE courier_id <> '$my_courier_id' and founded_date>='$datefrom'
        HAVING distance < '5'
        ORDER BY distance
        LIMIT 5;
 
Nahoru Odpovědět
19.1.2023 14:07
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:20.1.2023 7:50

No, ale, kdybys to potreboval rychle, tak je lepsi hnedka pri insertu spocitat bod mrizky a pak selectem vyberes jen ty v okoli bodu mrizky a jen u nich spocitas ty siny a kosiny. Co muze byt treba 100 bodu. Kdezto ted to pocitas pro vsech treba 10.000.000 :)

 
Nahoru Odpovědět
20.1.2023 7:50
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.