Ezt hogyan? SQL
Adott 2 tábla. Posztok és helyek.
Jelenleg 2 kéréssel működik a keresés:
SELECT longitude, latitude FROM locations WHERE zipcode = 1234
Majd még 1 select
SELECT name, (
6371 *
acos(cos(radians($lat)) *
cos(radians(latitude)) *
cos(radians(longitude) -
radians($lon)) +
sin(radians($lat)) *
sin(radians(latitude)))
) AS distance FROM posts WHERE name LIKE '%asd%' HAVING distance < 15
Nem lehetne ezt a kettőt egybe fűzni, és az első selectből kiszedett latitude és longitude értékekkel folytatná a kérést?
Locations táblában van:
id, zipcode, longitude, latitude
Posts táblaban pedig szintén van longitude és latitude
(Szerintem ez egy jobb megoldás, mint hogy Irányítószámok alapján keressek a posztok között, ha egy felhasználó beállít egy 200km-es sugarat, akkor kb 4000 irányítószám lesz a requestben ami valószínűleg nem túl baráti)
Ezen felül van még
name, description meg ilyesmi.
A $lon és $lat változók az első (SELECT longitude, latitude FROM locations WHERE zipcode = 1234) kérésből vannak
Szerintem
"SELECT longitude, latitude FROM locations WHERE zipcode = 1234" rész sima táblaként használható lenne subselect-ként, ha az sql motor tudja.
pl:
AS distance FROM posts, (SELECT longitude, latitude FROM locations WHERE zipcode = 1234) as coord_1 WHERE..
Csak a mezőnév ütközést és a megfelelő kapcsolódást kell megoldani.
Elvileg így kellene kinézni (nem teszteltem, a képletet sem ellenőriztem, hanem bemásoltam a tiedet):
~ ~ ~ ~ ~ ~ ~
SELECT name, 6371*
acos(cos(radians(locations.latitude))*
cos(radians(posts.latitude)) *
cos(radians(posts.longitude) -
radians(locations.longitude)) +
sin(radians(locations.latitude)) *
sin(radians(posts.latitude))) AS distance
FROM locations, posts
WHERE name LIKE '%asd%' AND zipcode=1234 AND 6371*
acos(cos(radians(locations.latitude)) *
cos(radians(posts.latitude)) *
cos(radians(posts.longitude) -
radians(locations.longitude)) +
sin(radians(locations.latitude)) *
sin(radians(posts.latitude)))<15;
~ ~ ~ ~ ~ ~ ~
HAVING-ot használva:
~ ~ ~ ~ ~ ~ ~
SELECT name, 6371*
acos(cos(radians(locations.latitude))*
cos(radians(posts.latitude)) *
cos(radians(posts.longitude) -
radians(locations.longitude)) +
sin(radians(locations.latitude)) *
sin(radians(posts.latitude))) AS distance
FROM locations, posts
WHERE name LIKE '%asd%' AND zipcode=1234
HAVING distance<15
~ ~ ~ ~ ~ ~ ~
HAVING-ot elkerülve, képletduplikáció nélkül:
~ ~ ~ ~ ~ ~ ~
SELECT * FROM
(SELECT name, 6371*
acos(cos(radians(locations.latitude))*
cos(radians(posts.latitude)) *
cos(radians(posts.longitude) -
radians(locations.longitude)) +
sin(radians(locations.latitude)) *
sin(radians(posts.latitude))) AS distance
FROM locations, posts
WHERE name LIKE '%asd%' AND zipcode=1234) tmp
WHERE distance<15
~ ~ ~ ~ ~ ~ ~
Meg lehetne talán még JOIN-nal is oldalni, de nem hiszem, hogy hatékonyabb lenne.
Igen a 9. válasz is rendben van. Nem szerencsés subquery-t használni, de aligha hiszem, hogy akkora adatbázisról lenne szó, hogy ez releváns problémát okozzon. A hátránya inkább az, hogy az irányítószám, mint paraméter három helyen szerepel benne.
> [A 9. válaszra reagálva] Viszont nem tudom, így nem lassabb, erőforrás igényesebb mint az eredeti megoldással?
Nem biztos, hogy ez releváns. Illetve azért az adatbáziskezelők is szanszét optimalizálják egy-egy lekérdezés lefutását, ennyire nem értek hozzá, de elképzelhetőnek tartom, hogy az adatbáziskezelő felismeri azt, hogy a három subquery ugyanazt az rekordot adja vissza, és egyszer futtatja le. Illetve ha pát ezer soros az a locations tábla, akkor ha háromszor is futtatja le, az sem okoz hatalmas terhelést, itt azért századmásodpercekről van szó. (Feltéve persze, ha megfelelően van indexelve az adatbázis, pl. a zipcode-ra van index a locations-ban.)
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!