5.2 Querying Spatial Data
The structures of a spatial layer are used to resolve spatial queries and spatial joins.
Spatial uses a two-tier query model with primary and secondary filter operations to resolve spatial queries and spatial joins, as explained in Query Model. The term two-tier indicates that two distinct operations are performed to resolve queries. If both operations are performed, the exact result set is returned.
You cannot append a database link (dblink) name to the name of a spatial table in a query if a spatial index is defined on that table.
- Spatial Query
- Spatial Join
- Data and Index Dimensionality, and Spatial Queries
- Using Event 54700 to Require a Spatial Index for Spatial Queries
Parent topic: Indexing and Querying Spatial Data
5.2.1 Spatial Query
In a spatial R-tree index, each geometry is represented by its minimum bounding rectangle (MBR), as explained in R-Tree Indexing. Consider the following layer containing several objects in Figure 5-1. Each object is labeled with its geometry name (geom_1 for the line string, geom_2 for the four-sided polygon, geom_3 for the triangular polygon, and geom_4 for the ellipse), and the MBR around each object is represented by a dashed line.
A typical spatial query is to request all objects that lie within a query window, that is, a defined fence or window. A dynamic query window refers to a rectangular area that is not defined in the database, but that must be defined before it is used. Figure 5-2 shows the same geometries as in Figure 5-1, but adds a query window represented by the heavy dotted-line box.
In Figure 5-2, the query window covers parts of geometries geom_1 and geom_2, as well as part of the MBR for geom_3 but none of the actual geom_3 geometry. The query window does not cover any part of the geom_4 geometry or its MBR.
- Primary Filter Operator
- Primary and Secondary Filter Operator
- Within-Distance Operator
- Nearest Neighbor Operator
- Spatial Functions
Parent topic: Querying Spatial Data
5.2.1.1 Primary Filter Operator
The SDO_FILTER operator, described in Spatial Operators , implements the primary filter portion of the two-step process involved in the Oracle Spatial query processing model. The primary filter uses the index data to determine only if a set of candidate object pairs may interact. Specifically, the primary filter checks to see if the MBRs of the candidate objects interact, not whether the objects themselves interact. The SDO_FILTER operator syntax is as follows:
SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)
In the preceding syntax:
-
geometry1
is a column of type SDO_GEOMETRY in a table. This column must be spatially indexed. -
geometry2
is an object of type SDO_GEOMETRY. This object may or may not come from a table. If it comes from a table, it may or may not be spatially indexed. -
param
is an optional string of type VARCHAR2. It can specify either or both of themin_resolution
andmax_resolution
keywords.
The following examples perform a primary filter operation only (with no secondary filter operation). They will return all the geometries shown in Figure 5-2 that have an MBR that interacts with the query window. The result of the following examples are geometries geom_1, geom_2, and geom_3.
Example 5-2 performs a primary filter operation without inserting the query window into a table. The window will be indexed in memory and performance will be very good.
Example 5-2 Primary Filter with a Temporary Query Window
SELECT A.Feature_ID FROM TARGET A WHERE sdo_filter(A.shape, SDO_geometry(SDO_POLYGON2D,NULL,NULL, SDO_elem_info_array(1,1003,3), SDO_ordinate_array(x1,y1, x2,y2)) ) = 'TRUE';
In Example 5-2, (x1,y1)
and (x2,y2)
are the lower-left and upper-right corners of the query window.
In Example 5-3, a transient instance of type SDO_GEOMETRY was constructed for the query window instead of specifying the window parameters in the query itself.
Example 5-3 Primary Filter with a Transient Instance of the Query Window
SELECT A.Feature_ID FROM TARGET A WHERE sdo_filter(A.shape, :theWindow) = 'TRUE';
Example 5-4 assumes the query window was inserted into a table called WINDOWS, with an ID of WINS_1.
Example 5-4 Primary Filter with a Stored Query Window
SELECT A.Feature_ID FROM TARGET A, WINDOWS B WHERE B.ID = 'WINS_1' AND sdo_filter(A.shape, B.shape) = 'TRUE';
If the B.SHAPE column is not spatially indexed, the SDO_FILTER operator indexes the query window in memory and performance is very good.
Parent topic: Spatial Query
5.2.1.2 Primary and Secondary Filter Operator
The SDO_RELATE operator, described in Spatial Operators , performs both the primary and secondary filter stages when processing a query. The secondary filter ensures that only candidate objects that actually interact are selected. This operator can be used only if a spatial index has been created on two dimensions of data. The syntax of the SDO_RELATE operator is as follows:
SDO_RELATE(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)
In the preceding syntax:
-
geometry1
is a column of type SDO_GEOMETRY in a table. This column must be spatially indexed. -
geometry2
is an object of type SDO_GEOMETRY. This object may or may not come from a table. If it comes from a table, it may or may not be spatially indexed. -
param
is a quoted string with themask
keyword and a valid mask value, and optionally either or both of themin_resolution
andmax_resolution
keywords, as explained in the documentation for the SDO_RELATE operator in Spatial Operators .
The following examples perform both primary and secondary filter operations. They return all the geometries in Figure 5-2 that lie within or overlap the query window. The result of these examples is objects geom_1 and geom_2.
Example 5-5 performs both primary and secondary filter operations without inserting the query window into a table. The window will be indexed in memory and performance will be very good.
Example 5-5 Secondary Filter Using a Temporary Query Window
SELECT A.Feature_ID FROM TARGET A WHERE sdo_relate(A.shape, SDO_geometry(SDO_POLYGON2D,NULL,NULL, SDO_elem_info_array(1,1003,3), SDO_ordinate_array(x1,y1, x2,y2)), 'mask=anyinteract') = 'TRUE';
In Example 5-5, (x1,y1)
and (x2,y2)
are the lower-left and upper-right corners of the query window.
Example 5-6 assumes the query window was inserted into a table called WINDOWS, with an ID value of WINS_1.
Example 5-6 Secondary Filter Using a Stored Query Window
SELECT A.Feature_ID FROM TARGET A, WINDOWS B WHERE B.ID = 'WINS_1' AND sdo_relate(A.shape, B.shape, 'mask=anyinteract') = 'TRUE';
If the B.SHAPE column is not spatially indexed, the SDO_RELATE operator indexes the query window in memory and performance is very good.
Parent topic: Spatial Query
5.2.1.3 Within-Distance Operator
The SDO_WITHIN_DISTANCE operator, described in Spatial Operators , is used to determine the set of objects in a table that are within n distance units from a reference object. This operator can be used only if a spatial index has been created on two dimensions of data. The reference object may be a transient or persistent instance of SDO_GEOMETRY, such as a temporary query window or a permanent geometry stored in the database. The syntax of the operator is as follows:
SDO_WITHIN_DISTANCE(geometry1 SDO_GEOMETRY, aGeom SDO_GEOMETRY, params VARCHAR2);
In the preceding syntax:
-
geometry1
is a column of type SDO_GEOMETRY in a table. This column must be spatially indexed. -
aGeom
is an instance of type SDO_GEOMETRY. -
params
is a quoted string of keyword value pairs that determines the behavior of the operator. See the SDO_WITHIN_DISTANCE operator in Spatial Operators for a list of parameters.
The following example selects any objects within 1.35 distance units from the query window:
SELECT A.Feature_ID FROM TARGET A WHERE SDO_WITHIN_DISTANCE( A.shape, :theWindow, 'distance=1.35') = 'TRUE';
The distance units are based on the geometry coordinate system in use. If you are using a geodetic coordinate system, the units are meters. If no coordinate system is used, the units are the same as for the stored data.
The SDO_WITHIN_DISTANCE operator is not suitable for performing spatial joins. That is, a query such as Find all parks that are within 10 distance units from coastlines will not be processed as an index-based spatial join of the COASTLINES and PARKS tables. Instead, it will be processed as a nested loop query in which each COASTLINES instance is in turn a reference object that is buffered, indexed, and evaluated against the PARKS table. Thus, the SDO_WITHIN_DISTANCE operation is performed n times if there are n rows in the COASTLINES table.
For non-geodetic data, there is an efficient way to accomplish a spatial join that involves buffering all geometries of a layer. This method does not use the SDO_WITHIN_DISTANCE operator. First, create a new table COSINE_BUFS as follows:
CREATE TABLE cosine_bufs UNRECOVERABLE AS SELECT SDO_BUFFER (A.SHAPE, B.DIMINFO, 1.35) FROM COSINE A, USER_SDO_GEOM_METADATA B WHERE TABLE_NAME='COSINES' AND COLUMN_NAME='SHAPE';
Next, create a spatial index on the SHAPE column of COSINE_BUFS. Then you can perform the following query:
SELECT /*+ ordered */ a.gid, b.gid FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 'COSINE_BUFS', 'SHAPE', 'mask=ANYINTERACT')) c, parks a, cosine_bufs b WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;
Parent topic: Spatial Query
5.2.1.4 Nearest Neighbor Operator
The SDO_NN operator, described in Spatial Operators , is used to identify the nearest neighbors for a geometry. This operator can be used only if a spatial index has been created on two dimensions of data. The syntax of the operator is as follows:
SDO_NN(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2 [, number NUMBER]);
In the preceding syntax:
-
geometry1
is a column of type SDO_GEOMETRY in a table. This column must be spatially indexed. -
geometry2
is an instance of type SDO_GEOMETRY. -
param
is a quoted string of keyword-value pairs that can determine the behavior of the operator, such as how many nearest neighbor geometries are returned. See the SDO_NN operator in Spatial Operators for information about this parameter. -
number
is the same number used in the call to SDO_NN_DISTANCE. Use this only if the SDO_NN_DISTANCE ancillary operator is included in the call to SDO_NN. See the SDO_NN operator in Spatial Operators for information about this parameter.
The following example finds the two objects from the SHAPE column in the COLA_MARKETS table that are closest to a specified point (10,7). (Note the use of the optimizer hint in the SELECT statement, as explained in the Usage Notes for the SDO_NN operator in Spatial Operators .)
SELECT /*+ INDEX(cola_markets cola_spatial_idx) */ c.mkt_id, c.name FROM cola_markets c WHERE SDO_NN(c.shape, SDO_geometry(SDO_POINT2D, NULL, SDO_point_type(10,7,NULL), NULL, NULL), 'sdo_num_res=2') = 'TRUE';
Parent topic: Spatial Query
5.2.1.5 Spatial Functions
Spatial also supplies functions for determining relationships between geometries, finding information about single geometries, changing geometries, and combining geometries. These functions all take into account two dimensions of source data. If the output value of these functions is a geometry, the resulting geometry will have the same dimensionality as the input geometry, but only the first two dimensions will accurately reflect the result of the operation.
Parent topic: Spatial Query
5.2.2 Spatial Join
A spatial join is the same as a regular join except that the predicate involves a spatial operator. In Spatial, a spatial join takes place when you compare all geometries of one layer to all geometries of another layer. This is unlike a query window, which compares a single geometry to all geometries of a layer.
Spatial joins can be used to answer questions such as Which highways cross national parks?
The following table structures illustrate how the join would be accomplished for this example:
PARKS( GID VARCHAR2(32), SHAPE SDO_GEOMETRY) HIGHWAYS( GID VARCHAR2(32), SHAPE SDO_GEOMETRY)
To perform a spatial join, use the SDO_JOIN operator, which is described in Spatial Operators . The following spatial join query, to list the GID column values of highways and parks where a highway interacts with a park, performs a primary filter operation only ('mask=FILTER'
), and thus it returns only approximate results:
SELECT /*+ ordered */ a.gid, b.gid FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 'HIGHWAYS', 'SHAPE', 'mask=FILTER')) c, parks a, highways b WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;
Note:
The SDO_JOIN operator is not supported when a composite B-tree spatial index is used.
The following spatial join query requests the same information as in the preceding example, but it performs both primary and secondary filter operations ('mask=ANYINTERACT'
), and thus it returns exact results:
SELECT /*+ ordered */ a.gid, b.gid FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 'HIGHWAYS', 'SHAPE', 'mask=ANYINTERACT')) c, parks a, highways b WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;
Parent topic: Querying Spatial Data
5.2.3 Data and Index Dimensionality, and Spatial Queries
The elements of a spatial query can, in theory, have the following dimensionality:
-
The base table geometries (or
geometry1
in spatial operator formats) can have two, three, or more dimensions. -
The spatial index created on the base table (or
geometry1
) can be two-dimensional or three-dimensional. -
The query window (or
geometry2
in spatial operator formats) can have two, three, or more dimensions.
Some combinations of dimensionality among the three elements are supported and some are not. Table 5-1 explains what happens with the possible combinations involving two and three dimensions.
Table 5-1 Data and Index Dimensionality, and Query Support
Base Table (geometry1) Dimensionality | Spatial Index Dimensionality | Query Window (geometry2) Dimensionality | Query Result |
---|---|---|---|
2-dimensional |
2-dimensional |
2-dimensional |
Performs a two-dimensional query. |
2-dimensional |
2-dimensional |
3-dimensional |
Supported if the query window has an appropriate SDO_GTYPE value less than 3008. |
2-dimensional |
3-dimensional |
2-dimensional |
Not supported: 3D index not permitted on 2D data. |
2-dimensional |
3-dimensional |
3-dimensional |
Not supported: 3D index not permitted on 2D data. |
3-dimensional |
2-dimensional |
2-dimensional |
Ignores the third (Z) dimension in each base geometry and performs a two-dimensional query. |
3-dimensional |
2-dimensional |
3-dimensional |
Supported if the query window has an appropriate SDO_GTYPE value less than 3008. |
3-dimensional |
3-dimensional |
2-dimensional |
Converts the 2D query window to a 3D window with zero Z values and performs a three-dimensional query. |
3-dimensional |
3-dimensional |
3-dimensional |
Performs a three-dimensional query. |
Parent topic: Querying Spatial Data
5.2.4 Using Event 54700 to Require a Spatial Index for Spatial Queries
Although a spatial index is recommended for spatial queries, by default is it not required. However, you can require that a spatial index be defined and used for spatial queries by setting event 54700 to the level
value 1
. You can reset the behavior to the default by setting event 54700 to the level
value 0
(zero).
You can apply the event for the session or system by using the ALTER SESSION or ALTER SYSTEM statement, respectively. For example:
ALTER SESSION set events '54700 trace name context forever, level 1';
The possible level
values are:
-
0 (default): Indicates that spatial queries can be performed even when a spatial index is not present on the query candidate geometry column.
-
1: Indicates indicates that spatial queries must have a spatial index present on the query candidate geometry column.
Parent topic: Querying Spatial Data