Difference between revisions of "Points"
m (→Příprava tabulek CUSTOMERS a STORES) |
m (→Vytvoření prostorového indexu) |
||
(43 intermediate revisions by the same user not shown) | |||
Line 58: | Line 58: | ||
postal_code VARCHAR2(9), | postal_code VARCHAR2(9), | ||
store_geo_location SDO_GEOMETRY); | store_geo_location SDO_GEOMETRY); | ||
+ | |||
+ | =====Vkládání dat s bodovou geometrií===== | ||
− | Pomocí příkazů INSERT začneme vkládat data do tabulek. Hodnoty | + | Pomocí příkazů INSERT začneme vkládat data do tabulek. Hodnoty vkládané do atributů ''cust_geo_location'' a ''store_geo_location'' jsou typu POINT (hodnota 2001 na pozici SDO_GTYPE), jsou vztaženy k souřadnicovému systému s kódem 8307 (atribut SDO_SRID), dále jsou uváděny souřadnice bodu (atribut SDO_POINT), zbývající atibuty SDO_ELEM_INFO a SDO_ORDINATES mají hodnoty NULL. Při vkládání souřadnic je nutné dát pozor na následující pravidlo: Oracle Locator vyžaduje, aby hodnota hodnotu zeměpisné délky byla umístěna před hodnotou zeměpisné šířky. |
− | + | ||
+ | Vkládání dat o zákaznících: | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1001,'Nichols', 'Alexandra', | (1001,'Nichols', 'Alexandra', | ||
'17 Maple Drive', 'Nashua', 'NH','03062', | '17 Maple Drive', 'Nashua', 'NH','03062', | ||
Line 68: | Line 71: | ||
SDO_POINT_TYPE (-71.48923,42.72347,NULL), NULL, NULL)); | SDO_POINT_TYPE (-71.48923,42.72347,NULL), NULL, NULL)); | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1002,'Harris', 'Melvin', | (1002,'Harris', 'Melvin', | ||
'5543 Harrison Blvd', 'Reston', 'VA', '20190', | '5543 Harrison Blvd', 'Reston', 'VA', '20190', | ||
Line 74: | Line 77: | ||
SDO_POINT_TYPE(-70.120133,44.795766,NULL), NULL, NULL)); | SDO_POINT_TYPE(-70.120133,44.795766,NULL), NULL, NULL)); | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1003,'Chang', 'Marian', | (1003,'Chang', 'Marian', | ||
'294 Main St', 'Concord', 'MA','01742', | '294 Main St', 'Concord', 'MA','01742', | ||
Line 80: | Line 83: | ||
SDO_POINT_TYPE (-71.351,42.4598,NULL), NULL, NULL)); | SDO_POINT_TYPE (-71.351,42.4598,NULL), NULL, NULL)); | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1004,'Williams', 'Thomas', | (1004,'Williams', 'Thomas', | ||
'84 Hayward Rd', 'Acton', 'MA','01720', | '84 Hayward Rd', 'Acton', 'MA','01720', | ||
Line 86: | Line 89: | ||
SDO_POINT_TYPE (-71.4559,42.4748,NULL), NULL, NULL)); | SDO_POINT_TYPE (-71.4559,42.4748,NULL), NULL, NULL)); | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1005,'Rodriguez', 'Carla', | (1005,'Rodriguez', 'Carla', | ||
'9876 Pine Lane', 'Sudbury', 'MA','01776', | '9876 Pine Lane', 'Sudbury', 'MA','01776', | ||
Line 92: | Line 95: | ||
SDO_POINT_TYPE (-71.4242,42.3826,NULL), NULL, NULL)); | SDO_POINT_TYPE (-71.4242,42.3826,NULL), NULL, NULL)); | ||
− | INSERT INTO customers VALUES | + | INSERT INTO customers VALUES |
(1006,'Adnani', 'Ramesh', | (1006,'Adnani', 'Ramesh', | ||
'1357 Appletree Ct', 'Falls Church', 'VA','22042 ', | '1357 Appletree Ct', 'Falls Church', 'VA','22042 ', | ||
Line 98: | Line 101: | ||
SDO_POINT_TYPE (-77.1745,38.88505,NULL),NULL,NULL)); | SDO_POINT_TYPE (-77.1745,38.88505,NULL),NULL,NULL)); | ||
− | + | Vkládání dat o obchodech. | |
− | INSERT INTO stores VALUES | + | INSERT INTO stores VALUES |
(101,'Nashua megastore', | (101,'Nashua megastore', | ||
'123 Commercial Way', 'Nashua', 'NH','03062', | '123 Commercial Way', 'Nashua', 'NH','03062', | ||
Line 106: | Line 109: | ||
SDO_POINT_TYPE (-71.49074,42.7229,NULL),NULL,NULL)); | SDO_POINT_TYPE (-71.49074,42.7229,NULL),NULL,NULL)); | ||
− | INSERT INTO stores VALUES | + | INSERT INTO stores VALUES |
(102,'Reston store', | (102,'Reston store', | ||
'99 Main Blvd', 'Reston', 'VA','22070', | '99 Main Blvd', 'Reston', 'VA','22070', | ||
Line 112: | Line 115: | ||
SDO_POINT_TYPE (-77.34511,38.9521,NULL),NULL,NULL)); | SDO_POINT_TYPE (-77.34511,38.9521,NULL),NULL,NULL)); | ||
− | -- | + | =====Vytvoření prostorového indexu===== |
+ | |||
+ | Tvorba prostorového indexu je složena ze dvou kroků, jejichž pořadí je nutné dodržet. Nejprve je nutné pro tabulku s prostorovými informacemi vložit záznam s příslušnými informacemi do systémové tabulky s metadaty. Příkaz INSERT je povolen i běžnému uživateli, ale vkládání záznamu se děje přes pohled USER_SDO_GEOM_METADATA. Ten umožňuje uživateli uložit hodnoty následujících sloupců: | ||
+ | (TABLE_NAME VARCHAR2(32), | ||
+ | COLUMN_NAME VARCHAR2(32), | ||
+ | DIMINFO SDO_DIM_ARRAY, | ||
+ | SRID NUMBER | ||
+ | ); | ||
+ | kde TABLE_NAME představuje název tabulky s prostorovými daty, COLUMN_NAME je název sloupce, který je typu SDO_GEOMETRY. DIMINFO je pole proměnlivou délkou (VARRAY(4)) obsahujícíc prvky typu SDO_DIM_ELEMENT. Atribut SRID obsahuje buď kód souřadnicového systému, ve kterém jsou lokalizovány geometrie prostorových objektů, nebo má zadánu hodnotu NULL, nejsou-li prvky spojeny s žádným konkrétním souřadnicovým systémem. | ||
+ | |||
+ | Definice SDO_DIM_ARRAY: | ||
+ | Create Type SDO_DIM_ARRAY as VARRAY(4) of SDO_DIM_ELEMENT; | ||
+ | |||
+ | kde SDO_DIM_ELEMENT je definován: | ||
+ | |||
+ | Create Type SDO_DIM_ELEMENT as OBJECT ( | ||
+ | SDO_DIMNAME VARCHAR2(64), | ||
+ | SDO_LB NUMBER, | ||
+ | SDO_UB NUMBER, | ||
+ | SDO_TOLERANCE NUMBER); | ||
+ | |||
+ | ''Příklady hodnot DIMINFO'': | ||
+ | *SS s kódem 8307 (WGS 84 coordinate system pro starší verze Oracle 8, 9 or 10gR1, později už EPSG 4326): | ||
+ | SDO_DIM_ARRAY (SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.5), | ||
+ | SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5) | ||
+ | ) | ||
+ | *Bez konkrétního SS (plocha o velikosti 100x100 s tolerancí 0.05): | ||
+ | SDO_DIM_ARRAY (SDO_DIM_ELEMENT('X', 0, 100, 0.05), | ||
+ | SDO_DIM_ELEMENT('Y', 0, 100, 0.05) | ||
+ | ) | ||
+ | |||
+ | Pole SDO_DIM_ARRAY má počet prvků n, odpovídající n dimenzím. Zde se DIMINFO skládá ze 2 instancí SDO_DIM_ELEMENT pro dvou-dimenzionální geometrie. Mohly by být 3 instance pro 3-dimenzionální geometrie nebo 4 pro 4-dimenzionální geometrie. Každá instance SDO_DIM_ELEMENT v poli musí být validní (nesmí mít NULL hodnotu) pro atributy SDO_LB (dolní mez), SDO_UB (horní mez) zájmového prostoru a SDO_TOLERANCE - toleranci, se kterou jsou dva body vnímány jako totožné. Tolerance představuje přesnost pro prostorová data a musí být větší než nula. | ||
+ | |||
+ | Pro náš příklad budeme vkládat záznamy s metainformacemi o obou tabulkách přes pohled USER_SDO_GEOM_METADATA: | ||
− | INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) | + | INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) |
VALUES ('CUSTOMERS', 'CUST_GEO_LOCATION', | VALUES ('CUSTOMERS', 'CUST_GEO_LOCATION', | ||
SDO_DIM_ARRAY | SDO_DIM_ARRAY | ||
Line 121: | Line 157: | ||
8307); | 8307); | ||
− | INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) | + | INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) |
VALUES ('STORES', 'STORE_GEO_LOCATION', | VALUES ('STORES', 'STORE_GEO_LOCATION', | ||
SDO_DIM_ARRAY | SDO_DIM_ARRAY | ||
Line 127: | Line 163: | ||
SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5)), | SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5)), | ||
8307); | 8307); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Uvedené meze pro dimenze longitude (-180.0, 180.0) a latitude (-90, 90) souvisí geodetickým datem, který používá souřadnicový systém WGS84. Hodnota tolerance 0.5 znamená, že jakékoli dva body ležící od sebe méně než půl metru, jsou považovány za stejný bod v případě funkcí nebo operací pracujícími s určováním polohy. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Teprve nyní můžeme přistoupit k tvorbě prostorového indexu. Prostorové indexy jsou nutné pro mnoho dotazů, které používají operátory modulu Locator, a pro výkon většiny prostorových dotazů jsou důležité, neboť jinak se vyhodnocování vztahů dopočítává teprve při vykonávání dotazu. Před použitím prostorových dat v analýzách či dotazování vytváříme prostorový index pro každý prostorový sloupec. Chcete-li vytvořit prostorové index, použijeme příkaz CREATE INDEX a v klauzuli pro INDEXTYPE použijeme typ MDSYS.SPATIAL_INDEX. | |
+ | Příkaz CREATE INDEX pak má v z8kladn9m tvaru následující složení(může obsahovat řadu parametrů, viz [http://docs.oracle.com/cd/B28359_01/appdev.111/b28400/sdo_objindex.htm#i78196]): | ||
+ | CREATE INDEX [schema.]index ON [schema.]table (column) | ||
+ | INDEXTYPE IS MDSYS.SPATIAL_INDEX; | ||
− | + | Název indexu je doporučeno poskládat z názvu tabulky, ke které je index tvořen a zkratky sidx (spatial index). Bude vytvořen na sloupci s typem SDO_GEOMETRY a je to prostorový index(mdsys.spatial_index). | |
− | + | Příkazy pro naše dvě tabulky pak vypadají takto: | |
+ | |||
+ | CREATE INDEX customers_sidx ON customers(cust_geo_location) INDEXTYPE IS mdsys.spatial_index; | ||
+ | CREATE INDEX stores_sidx ON stores(store_geo_location) INDEXTYPE IS mdsys.spatial_index; | ||
− | + | Teprve po vytvoření prostorového indexu můžeme využít prostředí GeoRaptoru pro zobrazení geoobjektů. Rozmístění obchodů a lokalizace zákazníků jsou patrny na obrázku [[Media:StoresCustomers.png | Obchody&Zakaznici]]. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | =====Prostorové dotazy nad bodovými daty===== | |
− | + | Teprve poté, kdy máme vytvořené a naplněné tabulky s prostorovými daty, aktualizovaná prostorová metadata a vytvořené prostorové indexy, můžeme začít používat operátory a funkce Oracle Locator v dotazech, kde práce s prostorem je vázána na definovanou lokalitu. | |
− | + | Chceme vyhledat tři nejbližší zákazníky pro obchod se store_id = 101. V příkazu SQL použijeme operátor SDO_NN ("nearest neighbor - nejbližší soused") ve formátu | |
+ | SDO_NN (geometry1, geometry2, param [, číslo]); | ||
+ | který používá prostorový index k identifikaci nejbližších sousedů ke geometrii. | ||
− | + | Význam operandů: | |
− | + | geometry1 Určuje geometrii sloupce v tabulce. Sloupec musí být prostorově zaindexován. Datovým typem je SDO_GEOMETRY. | |
− | + | geometry2 Určuje buď geometrii z tabulky nebo přechodnou geometrickou instanci. | |
− | + | Nejbližší soused nebo sousedé ke ''geometry2'' se vrací od ''geometry1''. Datový typ je SDO_GEOMETRY. | |
− | + | param Určuje chování operátoru. K dispozici jsou klíčová slova v tabulce 19-4. Pokud tento parametr nezadáte, | |
+ | operátor vrátí všechny řádky v pořadí podle rostoucí vzdálenosti od ''geometry2''. Datový typ je VARCHAR2. | ||
+ | number Pokud SDO_NN volá operátor SDO_NN_DISTANCE, který vrací nejmenší vzdálenost mezi geometriemi. Datový typ je NUMBER. | ||
− | + | Operátor SDO_NN vrací počet objektů ''geometry1'', které jsou nejblíže k objektům ''geometry2''. Při určování toho, jak blízko sebe jsou dva geometrické objekty, se použije nejkratší vzdálenost mezi dvěma body na obvodu/povrchu každého objektu. | |
− | + | Operand ''param'' může zahrnovat některý z následujících parametrů: | |
− | + | distance Určuje počet jednotek vzdálenosti, po kterém se přestane hledat nejbližší soused. | |
+ | Není-li zadána parametr unit, použije se unit(jednotka měření) stejná, jako mají data. | ||
+ | Datový typ je NUMBER. Například: "distance = 10 unit = míle" | ||
+ | sdo_batch_size Určuje počet řádků, které mají být hodnoceny v době, kdy provádění výrazu SDO_NN se vyhodnocuje vícekrát, | ||
+ | aby se vrátil požadovaný počet výsledků, které vyhovují klauzuli WHERE. | ||
+ | K dispozici je pouze tehdy, je-li použit index R-tree. Pokud zadáte sdo_batch_size = 0 | ||
+ | (nebo je-li parametr param zcela vynechán), Spatial modul vypočítá velikost dávky, která je vhodná pro velikost výsledné sady. | ||
+ | Datový typ je NUMBER. Například: 'sdo_batch_size = 10' | ||
+ | sdo_num_res Není-li uveden sdo_batch_size, určuje kolik výsledků (nejbližších sousedů) se má vrátit. | ||
+ | Pokud je zadán sdo_batch_size, je toto klíčové slovo ignorováno. | ||
+ | Datový typ je NUMBER. Například: 'sdo_num_res = 5' | ||
+ | unit Je-li užito klíčové slovo ''distance'' nebo je použito volání SDO_NN_DISTANCE, určuje jednotky měření. | ||
+ | Hodnoty jednotek SDO_UNIT jsou uvedeny v tabulce MDSYS.SDO_DIST_UNITS. | ||
+ | Datový typ je VARCHAR2. Výchozí = unit (jednotka měření) spojená s daty. | ||
+ | U geodetických dat je výchozí hodnotou metr. Například: 'jednotka = KM' | ||
− | + | Podrobnosti k operátoru SDO_NN najdete v dokumentaci Oracle kapitola 19 [http://docs.oracle.com/cd/B28359_01/appdev.111/b28400/sdo_operat.htm#i78067 Spatial Operators - SDO_NN]. | |
+ | V příkazu pro vyhledání tří nejblíže bydlících zákazníků u obchodu s id 101, bude použití SDO_NN vypadat takto: | ||
− | + | SELECT c.customer_id, c.first_name, c.last_name | |
− | + | FROM stores s, customers c | |
− | + | WHERE s.store_id = 101 | |
− | + | AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=3') = 'TRUE'; | |
− | + | ||
− | + | Pokud budeme chtít výsledek upravit tak, abychom dostali seznam nejbližších zákazníků setříděný podle vzdálenosti, kterou má zákazník k obchodu, pak lze využít operátoru SDO_NN_DISTANCE a podle jeho výsledků třídít. Podobně jako u operátoru SDO_NN je i tento operátor popsán v dokumentaci kapitola 19 [http://docs.oracle.com/cd/B28359_01/appdev.111/b28400/sdo_operat.htm#i80529 Spatial Operators - SDO_NN_DISTANCE]. | |
− | + | SELECT /*+ordered*/ c.customer_id, c.first_name, c.last_name, sdo_nn_distance (1) distance | |
− | + | FROM stores s, customers c | |
− | + | WHERE s.store_id = 101 | |
− | + | AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=3', 1) = 'TRUE' | |
− | + | ORDER BY distance; | |
− | |||
− | + | Kdo bydlí nejblíže obchodu 101 lze zjistit příkazem | |
− | + | SELECT c.customer_id, c.first_name, c.last_name | |
+ | FROM stores s, customers c | ||
+ | WHERE s.store_id = 101 | ||
+ | AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=1') = 'TRUE'; | ||
− | Spatial | + | Detailnější rozmístění obchodů a zákazníků ukazuje obrázek [[Media:StoresCustomersDetail.png | Lokalizace detailněji]]. |
+ | |||
+ | Dalším operátorem, jehož působení si ukážeme je SDO_WITHIN_DISTANCE (stránka dokumentace Oracle v kapitole 19 [http://docs.oracle.com/cd/B28359_01/appdev.111/b28400/sdo_operat.htm#i77653 Spatial Operators - SDO_WITHIN_DISTANCE]). Operátor na základě prostorového indexu identifikuje sadu prostorových objektů, které jsou do určité specifikované vzdálenosti od daného objektu, jako je například oblast zájmu nebo bod zájmu. Formát operátoru: | ||
+ | SDO_WITHIN_DISTANCE (geometry1, aGeom, params); | ||
+ | kde | ||
+ | geometry1 Určuje geometrie sloupce v tabulce. Polohu sady geometrických objektů operátor porovná s požadovanou vzdáleností od daného objektu (aGeom). | ||
+ | Sloupec musí být prostorově indexován. Datový typ je SDO_GEOMETRY. | ||
+ | aGeom Určuje objekt, který má být posouzen na vzdálenost od geometrických objektů v geometry1. | ||
+ | Zadává se buď geometrie z tabulky (pomocí proměnné vazby) nebo přechodná instance geometrie (pomocí SDO_GEOMETRY konstruktoru). | ||
+ | Datový typ je SDO_GEOMETRY. | ||
+ | params Udává v uvozovkách zadané řetězce obsahující jeden nebo více klíčových slov (s hodnotami), které určují chování operátoru. | ||
+ | Mohou to být položky (distance, max_resolution, min_resolution, querytype, a unit) | ||
+ | (vzdálenost, max_rozliseni, min_rozliseni, typDotazu, a jednotka) a jsou chápána jako potenciální klíčová slova pro parametr params. | ||
+ | Datový typ těchto hodnot je VARCHAR2. | ||
+ | Parametry operandu params: | ||
+ | distance Určuje hodnotu vzdálenosti. Je-li souřadný systém spojený s geometrií, vzdálenost používá jednotky spojené se souřadnicovým systémem. | ||
+ | Toto je povinný parametr. Datový typ je NUMBER. | ||
+ | max_resolution Zahrnuje pouze geometrie, u nichž alespoň u jedné strany z geometrie MBR (minimálního ohraničujícícho obdélníka) | ||
+ | je vzdálenost menší než nebo rovna zadané hodnotě. Například, max_resolution = 10 zahrnuje pouze geometrie, | ||
+ | pro které je šířka nebo výška (nebo oba) z geometrie MBR menší než nebo rovna 10. | ||
+ | min_resolution Zahrnuje pouze takové geometrie, pro které alespoň jedna strana geometrie MBR je rovna nebo větší než zadaná hodnota. | ||
+ | Například, min_resolution = 10 zahrnuje pouze geometrie, pro které je šířka nebo výška (nebo oba) z geometrie MBR nejméně 10. | ||
+ | querytype Nastavení 'querytype = FILTER' vede k prováděn9 pouze primárního filtru. | ||
+ | Není-li uveden querytype, pak se v operaci provedou oba filtry - jak primární, tak sekundární (výchozí nastavení). | ||
+ | Datový typ je VARCHAR2. | ||
+ | unit Určuje jednotku měření: 'unit= ', kde je hodnota SDO_UNIT převzata z tabulky MDSYS.SDO_DIST_UNITS (například 'unit = KM'). | ||
+ | Datový typ je NUMBER. Výchozí jednotka měření je spojena s daty, u geodetických dat je výchozí hodnota metr. | ||
− | + | Chceme-li tedy vyhledat zákazníky do vzdálenosti 50 mil od obchodu se store_id = 101, použijeme v podmínce za klíčovým slovem WHERE operátor SDO_WITHIN_DISTANCE s parametrem unit pro změnu jednotek na míle. | |
+ | |||
+ | SELECT /*+ordered*/ c.customer_id, c.first_name, c.last_name | ||
+ | FROM stores s, customers c | ||
+ | WHERE s.store_id = 101 | ||
+ | AND sdo_within_distance (c.cust_geo_location, s.store_geo_location, | ||
+ | 'distance = 50 unit=MILE') = 'TRUE'; | ||
− | + | Ve výsledku by to měli být tito 4 zákazníci: | |
+ | 1005 Carla Rodriguez | ||
+ | 1004 Thomas Williams | ||
+ | 1003 Marian Chang | ||
+ | 1001 Alexandra Nichols | ||
− | + | [http://gis.vsb.cz/wikivyuka/index.php/Prostorov%C3%A9_datab%C3%A1ze_-_cvi%C4%8Den%C3%AD Hlavní stránka předmětu] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 13:10, 24 March 2015
Příklad využívá podklady z Oracle dokumentace zaměřené na práci s modulem Locator.
Contents
Příprava tabulek CUSTOMERS a STORES
Uvedený příklad vychází z předpokladu, kdy obchodní společnost má několik maloobchodních prodejen. Aby prodejny mohly zákazníky, kteří jsou v blízkosti daného obchodu, informovat o nových reklamních akcích, je nutné uložit a uchovávat lokalizační údaje jak pro zákazníky, tak obchody. Pak je teprve možné najít odpovídající zákazníky a provádět analýzy využívající znalost polohy obchodu i zákazníků.
Data o Zákaznících budou uloženy v tabulce CUSTOMERS, která má takto definovanou strukturu:
CUSTOMERS( customer_id NUMBER, last_name VARCHAR2(30), first_name VARCHAR2(30), street_address VARCHAR2(40), city VARCHAR2(30), state_province_code VARCHAR2(2), postal_code VARCHAR2(9), cust_geo_location SDO_GEOMETRY)
Data o obchodech budou mít strukturu definovánou v tabulce STORES:
STORES( store_id NUMBER, description VARCHAR2(100), street_address VARCHAR2(40), city VARCHAR2(30), state_province_code VARCHAR2(2), postal_code VARCHAR2(9), store_geo_location SDO_GEOMETRY)
Než tabulky vytvoříme, je vhodné "vyčistit" databázi pro případ, že by tam už tabulky stejného jména existovaly. (Zejména v případě, že budeme akce opakovat:-)). Příkaz DROP vymaže z databáze tabulku nebo index daného jména, příkaz DELETE vymaže záznam, který je dán podmínkou za klíčovým slovem WHERE.
DROP TABLE customers; DROP TABLE stores; DROP INDEX customers_sidx; DROP INDEX stores_sidx; DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'CUSTOMERS' AND COLUMN_NAME = 'CUST_GEO_LOCATION'; DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'STORES' AND COLUMN_NAME = 'STORE_GEO_LOCATION';
Nyní je možné vytvořit pomocí příkazů CREATE obě tabulky:
CREATE TABLE customers ( customer_id NUMBER, last_name VARCHAR2(30), first_name VARCHAR2(30), street_address VARCHAR2(40), city VARCHAR2(30), state_province_code VARCHAR2(2), postal_code VARCHAR2(9), cust_geo_location SDO_GEOMETRY); CREATE TABLE stores ( store_id NUMBER, description VARCHAR2(100), street_address VARCHAR2(40), city VARCHAR2(30), state_province_code VARCHAR2(2), postal_code VARCHAR2(9), store_geo_location SDO_GEOMETRY);
Vkládání dat s bodovou geometrií
Pomocí příkazů INSERT začneme vkládat data do tabulek. Hodnoty vkládané do atributů cust_geo_location a store_geo_location jsou typu POINT (hodnota 2001 na pozici SDO_GTYPE), jsou vztaženy k souřadnicovému systému s kódem 8307 (atribut SDO_SRID), dále jsou uváděny souřadnice bodu (atribut SDO_POINT), zbývající atibuty SDO_ELEM_INFO a SDO_ORDINATES mají hodnoty NULL. Při vkládání souřadnic je nutné dát pozor na následující pravidlo: Oracle Locator vyžaduje, aby hodnota hodnotu zeměpisné délky byla umístěna před hodnotou zeměpisné šířky.
Vkládání dat o zákaznících:
INSERT INTO customers VALUES (1001,'Nichols', 'Alexandra', '17 Maple Drive', 'Nashua', 'NH','03062', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.48923,42.72347,NULL), NULL, NULL)); INSERT INTO customers VALUES (1002,'Harris', 'Melvin', '5543 Harrison Blvd', 'Reston', 'VA', '20190', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(-70.120133,44.795766,NULL), NULL, NULL)); INSERT INTO customers VALUES (1003,'Chang', 'Marian', '294 Main St', 'Concord', 'MA','01742', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.351,42.4598,NULL), NULL, NULL)); INSERT INTO customers VALUES (1004,'Williams', 'Thomas', '84 Hayward Rd', 'Acton', 'MA','01720', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.4559,42.4748,NULL), NULL, NULL)); INSERT INTO customers VALUES (1005,'Rodriguez', 'Carla', '9876 Pine Lane', 'Sudbury', 'MA','01776', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.4242,42.3826,NULL), NULL, NULL)); INSERT INTO customers VALUES (1006,'Adnani', 'Ramesh', '1357 Appletree Ct', 'Falls Church', 'VA','22042 ', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-77.1745,38.88505,NULL),NULL,NULL));
Vkládání dat o obchodech.
INSERT INTO stores VALUES (101,'Nashua megastore', '123 Commercial Way', 'Nashua', 'NH','03062', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.49074,42.7229,NULL),NULL,NULL)); INSERT INTO stores VALUES (102,'Reston store', '99 Main Blvd', 'Reston', 'VA','22070', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-77.34511,38.9521,NULL),NULL,NULL));
Vytvoření prostorového indexu
Tvorba prostorového indexu je složena ze dvou kroků, jejichž pořadí je nutné dodržet. Nejprve je nutné pro tabulku s prostorovými informacemi vložit záznam s příslušnými informacemi do systémové tabulky s metadaty. Příkaz INSERT je povolen i běžnému uživateli, ale vkládání záznamu se děje přes pohled USER_SDO_GEOM_METADATA. Ten umožňuje uživateli uložit hodnoty následujících sloupců:
(TABLE_NAME VARCHAR2(32), COLUMN_NAME VARCHAR2(32), DIMINFO SDO_DIM_ARRAY, SRID NUMBER );
kde TABLE_NAME představuje název tabulky s prostorovými daty, COLUMN_NAME je název sloupce, který je typu SDO_GEOMETRY. DIMINFO je pole proměnlivou délkou (VARRAY(4)) obsahujícíc prvky typu SDO_DIM_ELEMENT. Atribut SRID obsahuje buď kód souřadnicového systému, ve kterém jsou lokalizovány geometrie prostorových objektů, nebo má zadánu hodnotu NULL, nejsou-li prvky spojeny s žádným konkrétním souřadnicovým systémem.
Definice SDO_DIM_ARRAY:
Create Type SDO_DIM_ARRAY as VARRAY(4) of SDO_DIM_ELEMENT;
kde SDO_DIM_ELEMENT je definován:
Create Type SDO_DIM_ELEMENT as OBJECT ( SDO_DIMNAME VARCHAR2(64), SDO_LB NUMBER, SDO_UB NUMBER, SDO_TOLERANCE NUMBER);
Příklady hodnot DIMINFO:
- SS s kódem 8307 (WGS 84 coordinate system pro starší verze Oracle 8, 9 or 10gR1, později už EPSG 4326):
SDO_DIM_ARRAY (SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.5), SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5) )
- Bez konkrétního SS (plocha o velikosti 100x100 s tolerancí 0.05):
SDO_DIM_ARRAY (SDO_DIM_ELEMENT('X', 0, 100, 0.05), SDO_DIM_ELEMENT('Y', 0, 100, 0.05) )
Pole SDO_DIM_ARRAY má počet prvků n, odpovídající n dimenzím. Zde se DIMINFO skládá ze 2 instancí SDO_DIM_ELEMENT pro dvou-dimenzionální geometrie. Mohly by být 3 instance pro 3-dimenzionální geometrie nebo 4 pro 4-dimenzionální geometrie. Každá instance SDO_DIM_ELEMENT v poli musí být validní (nesmí mít NULL hodnotu) pro atributy SDO_LB (dolní mez), SDO_UB (horní mez) zájmového prostoru a SDO_TOLERANCE - toleranci, se kterou jsou dva body vnímány jako totožné. Tolerance představuje přesnost pro prostorová data a musí být větší než nula.
Pro náš příklad budeme vkládat záznamy s metainformacemi o obou tabulkách přes pohled USER_SDO_GEOM_METADATA:
INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) VALUES ('CUSTOMERS', 'CUST_GEO_LOCATION', SDO_DIM_ARRAY (SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.5), SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5)), 8307); INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID) VALUES ('STORES', 'STORE_GEO_LOCATION', SDO_DIM_ARRAY (SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.5), SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5)), 8307);
Uvedené meze pro dimenze longitude (-180.0, 180.0) a latitude (-90, 90) souvisí geodetickým datem, který používá souřadnicový systém WGS84. Hodnota tolerance 0.5 znamená, že jakékoli dva body ležící od sebe méně než půl metru, jsou považovány za stejný bod v případě funkcí nebo operací pracujícími s určováním polohy.
Teprve nyní můžeme přistoupit k tvorbě prostorového indexu. Prostorové indexy jsou nutné pro mnoho dotazů, které používají operátory modulu Locator, a pro výkon většiny prostorových dotazů jsou důležité, neboť jinak se vyhodnocování vztahů dopočítává teprve při vykonávání dotazu. Před použitím prostorových dat v analýzách či dotazování vytváříme prostorový index pro každý prostorový sloupec. Chcete-li vytvořit prostorové index, použijeme příkaz CREATE INDEX a v klauzuli pro INDEXTYPE použijeme typ MDSYS.SPATIAL_INDEX. Příkaz CREATE INDEX pak má v z8kladn9m tvaru následující složení(může obsahovat řadu parametrů, viz [1]):
CREATE INDEX [schema.]index ON [schema.]table (column) INDEXTYPE IS MDSYS.SPATIAL_INDEX;
Název indexu je doporučeno poskládat z názvu tabulky, ke které je index tvořen a zkratky sidx (spatial index). Bude vytvořen na sloupci s typem SDO_GEOMETRY a je to prostorový index(mdsys.spatial_index).
Příkazy pro naše dvě tabulky pak vypadají takto:
CREATE INDEX customers_sidx ON customers(cust_geo_location) INDEXTYPE IS mdsys.spatial_index; CREATE INDEX stores_sidx ON stores(store_geo_location) INDEXTYPE IS mdsys.spatial_index;
Teprve po vytvoření prostorového indexu můžeme využít prostředí GeoRaptoru pro zobrazení geoobjektů. Rozmístění obchodů a lokalizace zákazníků jsou patrny na obrázku Obchody&Zakaznici.
Prostorové dotazy nad bodovými daty
Teprve poté, kdy máme vytvořené a naplněné tabulky s prostorovými daty, aktualizovaná prostorová metadata a vytvořené prostorové indexy, můžeme začít používat operátory a funkce Oracle Locator v dotazech, kde práce s prostorem je vázána na definovanou lokalitu.
Chceme vyhledat tři nejbližší zákazníky pro obchod se store_id = 101. V příkazu SQL použijeme operátor SDO_NN ("nearest neighbor - nejbližší soused") ve formátu
SDO_NN (geometry1, geometry2, param [, číslo]);
který používá prostorový index k identifikaci nejbližších sousedů ke geometrii.
Význam operandů:
geometry1 Určuje geometrii sloupce v tabulce. Sloupec musí být prostorově zaindexován. Datovým typem je SDO_GEOMETRY. geometry2 Určuje buď geometrii z tabulky nebo přechodnou geometrickou instanci. Nejbližší soused nebo sousedé ke geometry2 se vrací od geometry1. Datový typ je SDO_GEOMETRY. param Určuje chování operátoru. K dispozici jsou klíčová slova v tabulce 19-4. Pokud tento parametr nezadáte, operátor vrátí všechny řádky v pořadí podle rostoucí vzdálenosti od geometry2. Datový typ je VARCHAR2. number Pokud SDO_NN volá operátor SDO_NN_DISTANCE, který vrací nejmenší vzdálenost mezi geometriemi. Datový typ je NUMBER.
Operátor SDO_NN vrací počet objektů geometry1, které jsou nejblíže k objektům geometry2. Při určování toho, jak blízko sebe jsou dva geometrické objekty, se použije nejkratší vzdálenost mezi dvěma body na obvodu/povrchu každého objektu.
Operand param může zahrnovat některý z následujících parametrů:
distance Určuje počet jednotek vzdálenosti, po kterém se přestane hledat nejbližší soused. Není-li zadána parametr unit, použije se unit(jednotka měření) stejná, jako mají data. Datový typ je NUMBER. Například: "distance = 10 unit = míle" sdo_batch_size Určuje počet řádků, které mají být hodnoceny v době, kdy provádění výrazu SDO_NN se vyhodnocuje vícekrát, aby se vrátil požadovaný počet výsledků, které vyhovují klauzuli WHERE. K dispozici je pouze tehdy, je-li použit index R-tree. Pokud zadáte sdo_batch_size = 0 (nebo je-li parametr param zcela vynechán), Spatial modul vypočítá velikost dávky, která je vhodná pro velikost výsledné sady. Datový typ je NUMBER. Například: 'sdo_batch_size = 10' sdo_num_res Není-li uveden sdo_batch_size, určuje kolik výsledků (nejbližších sousedů) se má vrátit. Pokud je zadán sdo_batch_size, je toto klíčové slovo ignorováno. Datový typ je NUMBER. Například: 'sdo_num_res = 5' unit Je-li užito klíčové slovo distance nebo je použito volání SDO_NN_DISTANCE, určuje jednotky měření. Hodnoty jednotek SDO_UNIT jsou uvedeny v tabulce MDSYS.SDO_DIST_UNITS. Datový typ je VARCHAR2. Výchozí = unit (jednotka měření) spojená s daty. U geodetických dat je výchozí hodnotou metr. Například: 'jednotka = KM'
Podrobnosti k operátoru SDO_NN najdete v dokumentaci Oracle kapitola 19 Spatial Operators - SDO_NN. V příkazu pro vyhledání tří nejblíže bydlících zákazníků u obchodu s id 101, bude použití SDO_NN vypadat takto:
SELECT c.customer_id, c.first_name, c.last_name FROM stores s, customers c WHERE s.store_id = 101 AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=3') = 'TRUE';
Pokud budeme chtít výsledek upravit tak, abychom dostali seznam nejbližších zákazníků setříděný podle vzdálenosti, kterou má zákazník k obchodu, pak lze využít operátoru SDO_NN_DISTANCE a podle jeho výsledků třídít. Podobně jako u operátoru SDO_NN je i tento operátor popsán v dokumentaci kapitola 19 Spatial Operators - SDO_NN_DISTANCE.
SELECT /*+ordered*/ c.customer_id, c.first_name, c.last_name, sdo_nn_distance (1) distance FROM stores s, customers c WHERE s.store_id = 101 AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=3', 1) = 'TRUE' ORDER BY distance;
Kdo bydlí nejblíže obchodu 101 lze zjistit příkazem
SELECT c.customer_id, c.first_name, c.last_name FROM stores s, customers c WHERE s.store_id = 101 AND sdo_nn (c.cust_geo_location, s.store_geo_location, 'sdo_num_res=1') = 'TRUE';
Detailnější rozmístění obchodů a zákazníků ukazuje obrázek Lokalizace detailněji.
Dalším operátorem, jehož působení si ukážeme je SDO_WITHIN_DISTANCE (stránka dokumentace Oracle v kapitole 19 Spatial Operators - SDO_WITHIN_DISTANCE). Operátor na základě prostorového indexu identifikuje sadu prostorových objektů, které jsou do určité specifikované vzdálenosti od daného objektu, jako je například oblast zájmu nebo bod zájmu. Formát operátoru:
SDO_WITHIN_DISTANCE (geometry1, aGeom, params);
kde
geometry1 Určuje geometrie sloupce v tabulce. Polohu sady geometrických objektů operátor porovná s požadovanou vzdáleností od daného objektu (aGeom). Sloupec musí být prostorově indexován. Datový typ je SDO_GEOMETRY. aGeom Určuje objekt, který má být posouzen na vzdálenost od geometrických objektů v geometry1. Zadává se buď geometrie z tabulky (pomocí proměnné vazby) nebo přechodná instance geometrie (pomocí SDO_GEOMETRY konstruktoru). Datový typ je SDO_GEOMETRY. params Udává v uvozovkách zadané řetězce obsahující jeden nebo více klíčových slov (s hodnotami), které určují chování operátoru. Mohou to být položky (distance, max_resolution, min_resolution, querytype, a unit) (vzdálenost, max_rozliseni, min_rozliseni, typDotazu, a jednotka) a jsou chápána jako potenciální klíčová slova pro parametr params. Datový typ těchto hodnot je VARCHAR2.
Parametry operandu params:
distance Určuje hodnotu vzdálenosti. Je-li souřadný systém spojený s geometrií, vzdálenost používá jednotky spojené se souřadnicovým systémem. Toto je povinný parametr. Datový typ je NUMBER. max_resolution Zahrnuje pouze geometrie, u nichž alespoň u jedné strany z geometrie MBR (minimálního ohraničujícícho obdélníka) je vzdálenost menší než nebo rovna zadané hodnotě. Například, max_resolution = 10 zahrnuje pouze geometrie, pro které je šířka nebo výška (nebo oba) z geometrie MBR menší než nebo rovna 10. min_resolution Zahrnuje pouze takové geometrie, pro které alespoň jedna strana geometrie MBR je rovna nebo větší než zadaná hodnota. Například, min_resolution = 10 zahrnuje pouze geometrie, pro které je šířka nebo výška (nebo oba) z geometrie MBR nejméně 10. querytype Nastavení 'querytype = FILTER' vede k prováděn9 pouze primárního filtru. Není-li uveden querytype, pak se v operaci provedou oba filtry - jak primární, tak sekundární (výchozí nastavení). Datový typ je VARCHAR2. unit Určuje jednotku měření: 'unit= ', kde je hodnota SDO_UNIT převzata z tabulky MDSYS.SDO_DIST_UNITS (například 'unit = KM'). Datový typ je NUMBER. Výchozí jednotka měření je spojena s daty, u geodetických dat je výchozí hodnota metr.
Chceme-li tedy vyhledat zákazníky do vzdálenosti 50 mil od obchodu se store_id = 101, použijeme v podmínce za klíčovým slovem WHERE operátor SDO_WITHIN_DISTANCE s parametrem unit pro změnu jednotek na míle.
SELECT /*+ordered*/ c.customer_id, c.first_name, c.last_name FROM stores s, customers c WHERE s.store_id = 101 AND sdo_within_distance (c.cust_geo_location, s.store_geo_location, 'distance = 50 unit=MILE') = 'TRUE';
Ve výsledku by to měli být tito 4 zákazníci:
1005 Carla Rodriguez 1004 Thomas Williams 1003 Marian Chang 1001 Alexandra Nichols