231 lines
9.1 KiB
Markdown
231 lines
9.1 KiB
Markdown
Trumpas programuotojo įvadas į PostGIS
|
|
======================================
|
|
|
|
Kai mokėmės duomenų bazių, paprastai pavyzdiniai duomenų bazių modeliai būdavo
|
|
gana panašūs vienas į kitą ir nuobodūs: sumodeliuoti biblioteką, sumodeliuoti
|
|
"draugų" duomenų bazę, ar gyvūnų klasifikaciją.
|
|
|
|
Šis įrašas parodys, kaip prie žinomų SQL duomenų tipų galima pridėti erdvinius,
|
|
ir kokias įdomias užklausas galime: sukursime tarptautinių oro uostų duomenų
|
|
bazę (nebijokite, duomenis importuosime), užduosime ir atsakysime keletą įdomių
|
|
klausimų.
|
|
|
|
Kas yra PostGis?
|
|
----------------
|
|
|
|
PostGis yra PostgreSQL priedas. PostGis prideda PostgreSQL naujų tipų ir
|
|
funkcijų, skirtų dirbti su erdviniais duomenimis. Ką tai reiškia? Išspręskime
|
|
užduotį ir sužinosime.
|
|
|
|
Duomenų bazės sukūrimas
|
|
-----------------------
|
|
|
|
Susikurkime PostgreSQL lentelę su viso pasaulio oro uostais (bent tais, kurie
|
|
turi [IATA kodą][1]). Oro uostų informaciją gausime iš [openflights.org][3].
|
|
|
|
```
|
|
$ ./managedb init
|
|
```
|
|
|
|
Visi skriptai ir `airports.dat` (oro uostų informacija) yra [šioje
|
|
repositorijoje][2]; skriptai nedideli, todėl labai rekomenduoju peržiūrėti bent
|
|
jau `sql` failus. Patikrinkime, kas viduje:
|
|
|
|
```
|
|
psql airportgames <<<"
|
|
SELECT
|
|
iata,
|
|
name,
|
|
to_char(st_y (geom), '999.99') AS latitude,
|
|
to_char(st_x (geom), '999.99') AS longitude,
|
|
to_char(st_z (geom), '9999') AS altitude
|
|
FROM
|
|
airports
|
|
WHERE
|
|
iata IN ('VNO', 'RIX', 'TLL');
|
|
"
|
|
iata | name | latitude | longitude | altitude
|
|
------+-------------------------------+----------+-----------+----------
|
|
TLL | Lennart Meri Tallinn Airport | 59.41 | 24.83 | 40
|
|
RIX | Riga International Airport | 56.92 | 23.97 | 11
|
|
VNO | Vilnius International Airport | 54.63 | 25.29 | 198
|
|
```
|
|
|
|
Matome Vilniaus, Rygos ir Talino oro uostų informaciją: IATA kodą, pavadinimą,
|
|
ilgumą, platumą, aukštį virš jūros lygio metrais.
|
|
|
|
Dabar, kai turime visus oro uostus, užduokime kelis įdomesnius klausimus apie
|
|
oro uostus.
|
|
|
|
Užklausos
|
|
---------
|
|
|
|
**Kokie oro uostai yra labiausiai nutolę vienas nuo kito?**
|
|
|
|
```
|
|
SELECT
|
|
a.country AS a_country,
|
|
a.iata AS a_iata,
|
|
b.country AS b_country,
|
|
b.iata AS b_iata,
|
|
to_char(st_distance (a.geom, b.geom, TRUE) / 1000, '99999.99') AS distance_km
|
|
FROM
|
|
airports a,
|
|
airports b
|
|
WHERE
|
|
a.iata != '\N'
|
|
AND b.iata != '\N'
|
|
AND a.gid > b.gid
|
|
ORDER BY
|
|
distance_km DESC
|
|
LIMIT 10;
|
|
|
|
a_country | a_iata | b_country | b_iata | distance_km
|
|
------------------+--------+-------------------------+--------+-------------
|
|
China | ZQZ | Argentina | OES | 20002.42
|
|
Saudi Arabia | KMX | French Polynesia | PUK | 20000.78
|
|
Indonesia | TKG | Colombia | MQU | 20000.53
|
|
French Polynesia | NAU | Ethiopia | AXU | 20000.47
|
|
Nicaragua | RNI | Cocos (Keeling) Islands | CCK | 20000.20
|
|
China | JGS | Argentina | TUC | 19999.93
|
|
Malaysia | LGL | Brazil | TFF | 19998.43
|
|
New Zealand | HLZ | Spain | ODB | 19998.36
|
|
Indonesia | PLM | Colombia | NVA | 19998.19
|
|
Malaysia | KBR | Peru | CHH | 19998.13
|
|
```
|
|
|
|
Turint galvoje, kad pusė atstumo aplink žemę ties ekvatoriais yra 20037.50 km
|
|
(ties poliais - 20004 km!), atstumas tarp tolimiausių oro uostų yra gana arti
|
|
teorinio maksimumo: trūksta tik 35km iki teorinio maksimumo ties ekvatoriumi,
|
|
ir tik 2km iki teorinio maksimumo ties poliais.
|
|
|
|
**Kurie oro uostai yra arčiausiai vienas kito?**
|
|
```
|
|
SELECT
|
|
a.country AS a_country,
|
|
a.iata AS a_iata,
|
|
b.country AS b_country,
|
|
b.iata AS b_iata,
|
|
to_char(st_y (a.geom), 'FMSG999.0000') || ',' || to_char(st_x (a.geom), 'FMSG999.0000') AS a_latlng,
|
|
to_char(st_y (b.geom), 'FMSG999.0000') || ',' || to_char(st_x (b.geom), 'FMSG999.0000') AS b_latlng,
|
|
to_char(st_distance (a.geom, b.geom, TRUE) / 1000, '99999.99') AS distance_km
|
|
FROM
|
|
airports a,
|
|
airports b
|
|
WHERE
|
|
a.iata != '\N'
|
|
AND b.iata != '\N'
|
|
AND a.gid > b.gid
|
|
ORDER BY
|
|
a.geom <-> b.geom ASC
|
|
LIMIT 10;
|
|
|
|
a_country | a_iata | b_country | b_iata | a_latlng | b_latlng | distance_km
|
|
------------------+--------+------------------+--------+--------------------+--------------------+-------------
|
|
Australia | JHQ | Australia | WSY | -20.2772,+148.7556 | -20.2761,+148.7550 | 0.14
|
|
Papua New Guinea | NDN | Papua New Guinea | KGW | -9.1436,+147.6842 | -9.1359,+147.6694 | 1.83
|
|
Papua New Guinea | KGW | Papua New Guinea | EFG | -9.1359,+147.6694 | -9.1538,+147.6598 | 2.24
|
|
Rwanda | GYI | Congo (Kinshasa) | GOM | -1.6772,+29.2589 | -1.6708,+29.2385 | 2.38
|
|
Papua New Guinea | NDN | Papua New Guinea | EFG | -9.1436,+147.6842 | -9.1538,+147.6598 | 2.92
|
|
Papua New Guinea | BNM | Papua New Guinea | KGW | -9.1078,+147.6667 | -9.1359,+147.6694 | 3.13
|
|
Virgin Islands | SPB | Virgin Islands | STT | +18.3386,-64.9407 | +18.3373,-64.9734 | 3.46
|
|
United States | SDM | Mexico | TIJ | +32.5723,-116.9800 | +32.5411,-116.9700 | 3.59
|
|
French Guiana | LDX | Suriname | ABN | +5.4831,-54.0344 | +5.5127,-54.0501 | 3.71
|
|
Papua New Guinea | BNM | Papua New Guinea | NDN | -9.1078,+147.6667 | -9.1436,+147.6842 | 4.40
|
|
```
|
|
|
|
140 metrų atstumu esantys JHQ ir WSY oro uostai Australijoje atrodo kaip tas
|
|
pats objektas. `NDN` ir `KGW` atrodo kaip du [skirtingi nupjautos žolės
|
|
ruožai, skirti nusileisti lėktuvams][4], užskaitysime! Ketvirtosios vietos
|
|
laimėtojus tarp Ruandos ir Kongo [skiria 2.38 km][8], ir tai jau tikri nemaži
|
|
oro uostai.
|
|
|
|
**Aukščiausiai virš jūros lygio esantys oro uostai?**
|
|
|
|
```
|
|
SELECT
|
|
iata,
|
|
name,
|
|
country,
|
|
to_char(st_z (geom), '9999') AS altitude_m
|
|
FROM
|
|
airports
|
|
ORDER BY
|
|
altitude_m DESC
|
|
LIMIT 10;
|
|
|
|
iata | name | country | altitude_m
|
|
------+----------------------------------------+---------+------------
|
|
DCY | Daocheng Yading Airport | China | 4411
|
|
BPX | Qamdo Bangda Airport | China | 4334
|
|
KGT | Kangding Airport | China | 4280
|
|
NGQ | Ngari Gunsa Airport | China | 4274
|
|
LPB | El Alto International Airport | Bolivia | 4071
|
|
POI | Capitan Nicolas Rojas Airport | Bolivia | 3936
|
|
YUS | Yushu Batang Airport | China | 3906
|
|
\N | Copacabana Airport | Bolivia | 3838
|
|
JUL | Inca Manco Capac International Airport | Peru | 3826
|
|
GMQ | Golog Maqin Airport | China | 3787
|
|
```
|
|
|
|
**Žemiausiai po jūros lygiu esantys oro uostai?**
|
|
|
|
```
|
|
SELECT
|
|
iata,
|
|
name,
|
|
country,
|
|
to_char(st_z (geom), 'FMSG999.00') AS altitude_m
|
|
FROM
|
|
airports
|
|
WHERE
|
|
iata != '\N'
|
|
ORDER BY
|
|
st_z (geom) ASC
|
|
LIMIT 10;
|
|
|
|
iata | name | country | altitude_m
|
|
------+--------------------------------------+---------------+------------
|
|
MTZ | Bar Yehuda Airfield | Israel | -385.88
|
|
EIY | Ein Yahav Airfield | Israel | -49.99
|
|
TRM | Jacqueline Cochran Regional Airport | United States | -35.05
|
|
GUW | Atyrau Airport | Kazakhstan | -21.95
|
|
RZR | Ramsar Airport | Iran | -21.34
|
|
ASF | Astrakhan Airport | Russia | -19.81
|
|
NSH | Noshahr Airport | Iran | -18.59
|
|
IPL | Imperial County Airport | United States | -16.46
|
|
NJK | El Centro NAF Airport (Vraciu Field) | United States | -12.80
|
|
RAS | Sardar-e-Jangal Airport | Iran | -12.19
|
|
```
|
|
|
|
Aukštai ir žemai esantiems oro uostams turbūt komentarų daug nereikia. Tik
|
|
abejais atvejais aiškūs pirmųjų vietų laimėtojai.
|
|
|
|
Pabaigai
|
|
--------
|
|
|
|
PostGis prie pažįstamos ir galingos PostgreSQL sąsajos suteikia erdvines
|
|
[funkcijas, duomenų tipus ir indeksavimo galimybes][9]. Jau žinant PostgreSQL,
|
|
importuoti erdvinius duomenis ir pradėti juos analizuoti yra gana nedidelis
|
|
šuolis.
|
|
|
|
Užduotys susidomėjusiam skaitytojui:
|
|
|
|
* Kodėl artimiausių oro uostų užklausoje naudojome [<->][5], o
|
|
tolimiausių -- [`st_distance`][6]?
|
|
* Kokį atstumą skristume aplink žemę, jei iš Vilniaus skristume visą laiką ta
|
|
pačia platuma?
|
|
* Kiek kartų reikia nuskristi United Economy klase aplink žemę Vilniaus
|
|
platumoje, kad uždirbtume [nemokamus pusryčius][7]?
|
|
|
|
|
|
[1]: https://en.wikipedia.org/wiki/International_Air_Transport_Association_code
|
|
[2]: https://github.com/motiejus/stud/tree/master/MTM/task4-straipsnis
|
|
[3]: https://openflights.org/data.html
|
|
[4]: https://goo.gl/maps/RD3d9fsH8NwzAnsYA
|
|
[5]: https://postgis.net/docs/geometry_distance_knn.html
|
|
[6]: https://postgis.net/docs/ST_Distance.html
|
|
[7]: https://www.united.com/ual/en/us/fly/mileageplus/premier/full-premier-benefits-chart.html
|
|
[8]: https://goo.gl/maps/3usBcUHDWnefVmab6
|
|
[9]: https://postgis.net/docs/reference.html
|