Une jointure spatiale est une opération de non-équijoin qui utilise une fonction de prédicat spatial pour évaluer la relation entre des objets géographiques dans deux tables. Cette relation sert ensuite de condition de jointure. Les cas d'utilisation courants consistent à déterminer si un point d'intérêt (POI) se trouve dans une zone spécifiée ou à analyser les intersections entre une trajectoire et une clôture géographique.
Limites
MaxCompute implémente les jointures spatiales via une jointure par diffusion (broadcast join). Vous devez utiliser une indication MAPJOIN pour spécifier la table la plus petite à diffuser.
Les fonctions de prédicat spatial prises en charge incluent ST_CONTAINS, ST_COVERS, ST_WITHIN et ST_INTERSECTS.
Les types de jointure pris en charge sont INNER JOIN, LEFT JOIN (qui diffuse la table de droite) et RIGHT JOIN (qui diffuse la table de gauche).
Exemples
Exemple 1
Créez deux zones non chevauchantes et plusieurs points à l'intérieur de celles-ci. Les données géométriques sont stockées au format WKT.
CREATE OR REPLACE TABLE areas (
area_id BIGINT,
area_name STRING,
geometry_detail STRING
);
INSERT OVERWRITE TABLE areas VALUES
(1, 'area_1', 'POLYGON((100 30, 110 30, 110 40, 100 40, 100 30))'),
(2, 'area_2', 'POLYGON((120 30, 130 30, 130 40, 120 40, 120 30))');
CREATE OR REPLACE TABLE points (
point_id BIGINT,
point_name STRING,
location STRING
);
INSERT OVERWRITE TABLE points VALUES
(1, 'point_1', 'POINT(105 35)'), -- Falls within area_1
(2, 'point_2', 'POINT(108 38)'), -- Falls within area_1
(3, 'point_3', 'POINT(102 32)'), -- Falls within area_1
(4, 'point_4', 'POINT(125 35)'), -- Falls within area_2
(5, 'point_5', 'POINT(128 39)'); -- Falls within area_2
Interrogez les points dans chaque zone. Une indication MAPJOIN est requise pour spécifier la table la plus petite lors d'une jointure spatiale.
Étant donné que les calculs géospatiaux sont généralement complexes, utilisez SET odps.stage.mapper.split.size=10; pour réduire la taille des fragments, ce qui augmente la concurrence de l'étape Map.
-- To support the GEOGRAPHY data type, enable the 2.0 type system.
SET odps.sql.type.system.odps2=true;
SELECT /*+MAPJOIN(a)*/
a.area_name,
a.area_id,
r.point_name,
r.point_id
FROM areas a, points r
WHERE ST_CONTAINS(ST_GEOGFROMTEXT(a.geometry_detail), ST_GEOGFROMTEXT(r.location))
ORDER BY a.area_name, r.point_id LIMIT 10;
-- Result:
+-----------+------------+------------+------------+
| area_name | area_id | point_name | point_id |
+-----------+------------+------------+------------+
| area_1 | 1 | point_1 | 1 |
| area_1 | 1 | point_2 | 2 |
| area_1 | 1 | point_3 | 3 |
| area_2 | 2 | point_4 | 4 |
| area_2 | 2 | point_5 | 5 |
+-----------+------------+------------+------------+
Exemple 2
Créez deux zones non chevauchantes et plusieurs points. Les polygones de zone sont stockés sous le type de données GEOGRAPHY, et les emplacements des points sont stockés sous forme de valeurs de longitude et de latitude de type DOUBLE.
CREATE OR REPLACE TABLE residential_areas (
area_id BIGINT,
area_name STRING,
geog GEOGRAPHY
);
INSERT OVERWRITE TABLE residential_areas VALUES
(1, 'area_1', ST_GEOGFROMTEXT('POLYGON((100 30, 110 30, 110 40, 100 40, 100 30))')),
(2, 'area_2', ST_GEOGFROMTEXT('POLYGON((120 30, 130 30, 130 40, 120 40, 120 30))'));
CREATE OR REPLACE TABLE restaurants (
restaurant_id BIGINT,
restaurant_name STRING,
lon DOUBLE,
lat DOUBLE
);
INSERT OVERWRITE TABLE restaurants VALUES
(1, 'restaurant_1', 105, 35), -- In area_1
(2, 'restaurant_2', 108, 38), -- In area_1
(3, 'restaurant_3', 125, 35), -- In area_2
(4, 'restaurant_4', 150, 50), -- Not in any area
(5, 'restaurant_5', 102, 32); -- In area_1
Interrogez la zone contenant chaque point et utilisez une jointure LEFT JOIN pour inclure également les points qui ne se trouvent dans aucune zone.
SELECT /*+MAPJOIN(a)*/
a.area_name,
r.restaurant_id
FROM restaurants r LEFT JOIN residential_areas a
ON ST_CONTAINS(a.geog, ST_GEOGPOINT(r.lon, r.lat))
ORDER BY a.area_name, r.restaurant_id LIMIT 10;
-- Result:
+-----------+---------------+
| area_name | restaurant_id |
+-----------+---------------+
| NULL | 4 |
| area_1 | 1 |
| area_1 | 2 |
| area_1 | 5 |
| area_2 | 3 |
+-----------+---------------+