Il existe une différence fondamentale entre une géométrie et la représentation objet de ce dernier. Un objet peut être binairement différent d’un autre, malgré que leur géométrie soient égales. Démonstration avec SQL Server et PostGreSQL/PostGIS…
voici donc 3 objets, des carrés pour faire simple. Créons la table et assignons les valeurs :
CREATE TABLE T_GEO
(geo1 GEOMETRY,
geo2 GEOMETRY,
geo3 GEOMETRY)
INSERT INTO T_GEO
VALUES ('POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))',
'POLYGON((2 1, 1 1, 1 2, 2 2, 2 1))',
'POLYGON((2 1, 2 2, 1 2, 1 1, 2 1))');
Voici les images de nos carrés :
D’accord je dessine horriblement mal… mais c’est fait exprès !
Testons si l’objet « géo1″ est égal à « go2 et/ou « geo3″
La requête SQL Server :
SELECT 'geo1 comparé à geo2' AS COMPARAISON,
CASE WHEN geo1.STEquals(geo2) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN geo1.STAsBinary() = geo2.STAsBinary()
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO
UNION ALL
SELECT 'geo1 comparé à geo3',
CASE WHEN geo1.STEquals(geo3) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN geo1.STAsBinary() = geo3.STAsBinary()
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO;
La requête PG :
SELECT 'geo1 comparé à geo2' AS COMPARAISON,
CASE WHEN ST_Equals(geo1, geo2) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN ST_AsBinary(geo1) = ST_AsBinary(geo2)
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO
UNION ALL
SELECT 'geo1 comparé à geo3',
CASE WHEN ST_Equals(geo2, geo3) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN ST_AsBinary(geo2) = ST_AsBinary(geo3)
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO;
Le résultat :
COMPARAISON GEO_EGAL BIN_EGAL
------------------- -------- --------
geo1 comparé à geo2 OUI NON
geo1 comparé à geo3 OUI NON
Aucun des objets n’est binairement égal à un autre, car nous n’avons pas pris le même point de départ et tourné différemment. Mais tous sont la même forme géométrique.
Pour vous en convaincre, superposons-les :
Bon, d’accord mes talents de dessinateur sont nuls… mais justement cela vous permet de voir que ce sont bien les mêmes objets… Si j’étais parfait vous n’auriez rien vu !
CQFD
NOTA : Au passage, notez les subtiles différences entre les requêtes :
1) SQL Server ne met pas de blanc souligné entre le préfixe ST et le reste du nom de la fonction.
2) SQL Server utilise une méthode et non une fonction. La méthode étant appliquée à l’objet celle ci est préfixé par l’objet en pointage.
PostGreSQL est parfaitement conforme à la norme SQL tandis que SQL Server ne l’est pas. Le choix MS peut paraître curieux, mais comme dans SQL Server se sont de véritables objets de type CLR (.net) qui sont stockées pour la géométrie et la géographie, et que par conséquent on y applique des méthodes, Microsoft à préférer ne pas induire en erreur en supprimant le blanc souligné et ainsi pourvoir revenir sur une notation normative au cas ou…
Vous pouvez d’ailleurs faire vous même cette compatibilité…
Exemple :
CREATE FUNCTION dbo.ST_Equals(@G1 GEOMETRY, @G2 GEOMETRY)
RETURNS BIT
AS
BEGIN
RETURN @G1.STEquals(@G2);
END
GO
CREATE FUNCTION dbo.ST_AsBinary (@G GEOMETRY)
RETURNS VARBINARY(max)
AS
BEGIN
RETURN @G.STAsBinary();
END
Mais nous ne sommes pas très avancés, car il faut maintenant utiliser le schéma dbo pour appeler nos fonctions…
SELECT 'geo1 comparé à geo2' AS COMPARAISON,
CASE WHEN dbo.ST_Equals(geo1, geo2) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN dbo.ST_AsBinary(geo1) = dbo.ST_AsBinary(geo2)
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO
UNION ALL
SELECT 'geo1 comparé à geo3',
CASE WHEN dbo.ST_Equals(geo2, geo3) = 1
THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
CASE WHEN dbo.ST_AsBinary(geo2) = dbo.ST_AsBinary(geo3)
THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM T_GEO;
--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *