SELECT ... ORDER BY Druh, Vzdálenost

Chtěl bych si přes SQLite udělat SELECT ID z geogetí DB a setřídit jej podle Druh, Vzdálenost.
SELECT id FROM geocache ORDER BY cachetype

Druh je mi jasný, ale nevím si rady s položkou Vzdalenost

vzdalenost tezko muze byt v dataazi, protoze by mohla byt jen vuci nejakemu pevne danemu bodu. k cemu by to bylo? Takze vzdalenost si musi spocitat a podle ni si ty data seradit sam.

Pevně daný bod je HOME COORDINATE.
Nacpal jsem do GG různé kategorie bodů (cachetype) a chtěl bych (dle kategorie) ty nejblíže HOME COORDINATE navštívit.
Představoval jsem si to tak, že si pomocí SELECTu vyberu setříděnou množinu bodů, která je nejblíže HOME COORDINATE.
Je to realizovatelné?

…nechápu proč si to nefiltruješ přímo v GG

Selectovat vzdálenost nejde, ledaže by se předem do databáze uložila. Pro HC by to asi i mělo smysl.
Obecnou vzdálenost dvou bodů (byť by jeden byl jako konstanta v selectu) pomocí SQLite selectovat nejde, protože pro vzdálenost na kouli (nemluvě o geoidu) jsou zapotřebí siny a cosiny a na to je její SQL příliš lite.

Přes GUI GeoGetu lze velmi pokročile filtrovat, zato řadit lze jen jednodušše - podle jednoho sloupce. Takže podle druhu a vzdálenosti nelze. V selectu takovéhle omezení není, zase tam ale chybí zrovna ta vzdálenost.

Řešení by bylo vlastním skriptem naplnit vlastní tag ve, kterém by ve vhodném formátu byly potřebné údaje v jednom textu. A pak podle sloupce s tímto tagem seznam setřídit.

Je to tady děsná skládačka ze spousty malých kousků :o

zlaty mysql :slight_smile:

Přesnou vzdálenost skutečně v SELECTU nespočítáš, ale pro malé okolí stačí přiblížení podle Pythagorovy věty.



SELECT id FROM geocache WHERE ...
ORDER BY ((`x`-refX)*(`x`-refX)+(`y`-refY)*(`y`-refY))

Odmocnina už není nutná, ta ti pořadí nezmění. Může se stát, že se ti někde pořadí přehodí, ale asi to nebude nic fatálního. Přesnou vzdálenost si musíš přepočítat z načtených dat.

A pokud te zajimaji body do urcite vzdalenosti, tak pro nejaky konkretrni rozsah X a Y souradnic muzes pouzit subselect na dvourozmerny souradnicovy index, ktery v Geogetu je a je velmi rychly.

SQLite umí používat extension (pluginy). Takže by mělo jít vytvořit funkci, která z X a Y spočte vzdálenost a funkci lze pak použít pro třídění. Mám dojem, že GeoGet používá interně tento mechanismus pro kompresi dat. Jen nevím, jestli by šlo z GG pluginu takovou vlastnost použít.
Viz http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions

Samozrejmne, ze do SQLite jsou pridavat funkce. Uz ted tam ma geoget pridane funkce na odstraneni diakritiky, kompresi a dekompresi dat, na regularni vyrazy a na prevod ciselneho datumu do formy, se kterou umi pracovat date funkce v sqlite.

Pridat ale funkci primo ze skriptu nejde a je otazka, jestli to vubec nekdy pujde. Nicmene pokud mas extension DLL, ktera v sbe tu funkcima, pak by to zavedeni pres SELECT load_extension(‘filename’); melo fungovat.

Děkuji všem za rady, ale některé poněkud přesahují mé IQ :wink:
Zeptal bych se ještě takhle… pokud bych chtěl z aktuálního Seznamu v GG vyexportovat vlastním exportním skriptem (což jsem jakž takž zvládl) i sloupec Vzdálenost, tak to taky musím počítat? Nebo to dostanu z nějaké proměnné?

neni. v sqlite jdou definovat user funkce. ale asi to je zybtečně složité
stačí zaregistrovat funkci function regexp($exp, $pattern)
{
return (bool) preg_match("/$pattern/i", $exp);
}.

Jinak se to obejde bez sinu a kosu, lze užít linearni aproximaci pro male vzdalenosit

Tak jsem se vzepjal k výkonu :wink: a vlastní fci na spočítání vzdálenosti mám hotovou.
Z SQLite shellu ji nalouduji, jak jsi psal - díky. Ještě by mě zajímalo jak to má GG s těmi vlastními přidanými fcemi - to je taky louduje při každém startu GG?

Jo, a ještě by mě zajímal ten ‘subselect na dvourozmerny souradnicovy index’ jak jsi psal o pár příspěvků výše. Byl by nějaký praktický příklad?

ANo. Ty funkce nejsou ulzoeny v databazi, po kazdem otevreni databaze se tam musi zaregistrovat.

SELECT key FROM coord_index WHERE minx>=:minx AND maxx<=:maxx AND miny>=:miny AND maxy<=:maxy

kde :minx :maxx :miny :maxy urcuji pozadovane rozsahy soyradnic Vlastne tak specifikujes obdelnik, a ono ti to vrati klice z tabulky Geocache tech kesi, ktere jsou uvnitr toho obdelniku.

subselect na dvourozmerny souradnicovy index’ je pozoruhodná věc. Zdá se, že je SQLite pro GeoGet jako dělaná.
Nenašel jsem tu o tom žádné zmínky, jen popis na http://www.sqlite.org/rtree.html. Nicmeně to je jen pro výběr, pro řazení, což byl původní dotaz, to asi moc použít nejde.

S řazením dle vzdálenosti, které se běžně používá i na gc.com, je ještě jiný praktický problém: Čím dále od počátku, tím více je nepěkné, že po sobě následují od sebe hodně vzdálené keše. Např. po keši vzdálené 5 km je keš vzdálená 5,1 km, ale protože je na zcela opačné straně, je od předešlé keše vzdálená 10 km.
Pro praktické použití by bylo lepší keše v seznamech řadit tak, že by nemusela strikně narůstat jejich vzdálenost od referenčního bodu, ale zato by platilo, že keše blízko u sebe ve výpisu, jsou i blízko ve skutečnosti. Řešit by to šlo procházením po nějaké vhodné spirále:
např. logaritmické:

nebo dokonce Daisy:

Jak to ale provést prakticky je trochu oříšek. :slight_smile:

Zkusil jsem napsal SQLite extension jako DLL, je to celkem jednoduché. V SQLite Expert ho bez problému zavedu a použiju, ale v GG mi příkaz SELECT load_extension (‘xxxx.dll’) vrátí chybu "not authorized". Šlo by nějak zařídit, aby natažení fungovalo?

Aha, zapomnel jsem, ze tenhle druh nahravani musim nejdrive povolit. :wink: Takze by to melo jit. Zkusim do pristi verze nezapomenout.

To by bylo skvělé! Tím se otevírají netušené možnosti :slight_smile:

Užitečné by bylo doplnit, jako externí, funkci PointDistance, aby se podmínka na vzdálenost, příp. řazení dle vzdálenosti, dalo dělat přímo v selectech.

PointDistance je pro tento ucel zbytecne presna a pomala funkce. Nicmene kdyz budes moci zavest vlastni extension, tak si tam muzes pridat i libovolnou vlastni funkci. Krom toho, kdyz budes mit tu extension DLL hotovou, tak si ji zavedes treba z konzole, nebo v libovolnem jinem programu.