IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Problème de fonction spatiale SQL-Server


Sujet :

Développement SQL Server

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut Problème de fonction spatiale SQL-Server
    Bonjour à tous,

    Voici mon petit problème.

    J'utilise une fonction ( .Reduce(x) ) sur un type geometry. Ce sont des multipolygones. La fonction marche et ne renvoie pas d'erreur avec ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     update Zone_VE set geom_simpl = geom.Reduce(2000);
    Le problème s'est que je récupère une géométrie de type multipoint, , je perds donc tout mes multipolygones....

    J'ai lu dans la doc que tout les types de geometry était pris en compte, mais ca devrait normalement conserver le type de géométrie.

    Si quelqu'un à une idée sur le problème ou même (soyons fou) une solution je suis preneur,

    Merci d'avance !

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Jouez sur le niveau de réduction...
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DECLARE @GEO GEOMETRY
    SET @GEO = 'POLYGON ((0 0, 1 1, 2 2 , 3 3, 3 0, 0 0))'
    SELECT @GEO.Reduce(1).STAsText()
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    POLYGON ((0 0, 3 3, 3 0, 0 0))
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    Merci tout d'abord de la réponse rapide,

    Bon j'ai essayé avec 1 en paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    update Zone_VE set geom_simpl = geom.Reduce(1);
    et du coup j'ai un résutat plutôt bizarre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ------------------------ | --------------------------------------------...
    Geometry original:       | Résultat :
    MULTIPOLYGON (((13.55157 | GEOMETRYCOLLECTION (POINT (13.55157470703125...
    MULTIPOLYGON (((-74.1210 | GEOMETRYCOLLECTION (POINT (-74.12109375 83.0...
    MULTIPOLYGON (((140.9739 | GEOMETRYCOLLECTION (POINT (140.9739685058593...
    MULTIPOLYGON (((58.18933 | GEOMETRYCOLLECTION (LINESTRING (59.375610351...
    MULTIPOLYGON (((19.82496 | GEOMETRYCOLLECTION (POINT (19.82496643066406...
    MULTIPOLYGON (((-1.83583 | GEOMETRYCOLLECTION (POINT (-1.83583450317382...
    MULTIPOLYGON (((35.47556 | GEOMETRYCOLLECTION (POLYGON ((34.90316390991...
    MULTIPOLYGON (((8.911651 | GEOMETRYCOLLECTION (POINT (8.911651611328125...
    Je n'arrive toujours pas à conserver mes multipolygones ....
    flûte!


    En fait, c'est bon ca marche avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    update Zone_VE set geom_simpl = geom.Reduce(0.00001);
    Merci encore , j'espère que la généralisation de mes entités sera efficace même avec ce niveau de réduction !

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Vous n'avez pas des polygones "à plat" ?

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    Eeuuuuh des polygones "à plat" ??

    J'ai des multipolygones, souvent une entité avec ses extensions regroupé sous un seul et unique identifiant. exemple : La France avec toutes ses îles...

    Ca change quelque chose?


    Sinon j'ai été un peu vite en besogne. Dans mes multipolygones, certains polygones sont très petits (genre les micro-îles), avec la fonction .Reduce(x) ces derniers suivant leurs taille sont transformés en Linestring ou carrément en point s'ils sont vraiment petits.

    Il est donc normal que je récupère un autre type de géométrie en sortie.

    J'envisage donc deux solutions hypothétiques :
    - L'une serait d'utiliser la fonction .Reduce(x) en l’empêchant de travailler sur des polygones à trois points (ce qui empêcherait d'avoir des linestring ou des point) mais cette solution me parait impossible.
    -La seconde serait une fonction qui supprimerait mes points et mes linestring dans mes geometries en sortie qui sont des GEOMETRY COLLECTION. En gros la transformer en Multipolygone.

    Si quelqu'un sait comment faire pour la seconde solution....

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Dans une GEOMETRY COLLECTION, chaque objet géométrique a une position ordinale.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DECLARE @GEO GEOMETRY
    SET @GEO = 'GEOMETRYCOLLECTION(POINT(0 0), POLYGON ((0 0, 1 1, 2 2 , 3 3, 3 0, 0 0)))'
    DECLARE @N INT
    SET @N = @GEO.STNumGeometries()
    WHILE @N >= 1
    BEGIN
       SELECT @GEO.STGeometryN(@N).STAsText()
       SET @N -= 1   
    END
    Peut être devriez vous venir à mon cours : http://www.orsys.fr/pdf-auto/pdfCours/TIA.pdf

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    OK, pour la position, du coup j'ai voulu faire ma deuxième solution, j'arrive au curseur suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    declare @idx_tot integer
    declare @num_entite integer
    declare @champ1 integer
    declare	@idx integer
    declare	@type varchar(50);
     
    declare Cursor_geom cursor   FOR
    select id_z_ve, Geom_simpl.STNumGeometries() from Zone_VE 
    open Cursor_geom
    fetch next FROM Cursor_geom INTO @num_entite, @champ1 
    while @@fetch_status = 0
    	begin
    	set @idx_tot = @champ1
    	set	@idx = 1
    		while @idx <= 5--@idx_tot
    			begin
    				set @type = exec('select geom_simpl.STGeometryN('+@idx+').STGeometryType() from Zone_VE')
    				if @type <> 'Polygon'
    					if @type <> 'MultiPolygon'
    					exec('update Zone_VE set geom_simpl =  geom_simpl.STDifference(select geom_simpl.STGeometryN('+@idx+') 
    										from Zone_VE )
    										 where id_z_ve = '+@num_entite+' ')
    				--print @idx
    				set @idx = @idx+1
    			end
    		fetch next FROM Cursor_geom INTO  @num_entite,@champ1 
        end
    close Cursor_geom
    deallocate Cursor_geom
    Évidemment ce dernier ne fonctionne pas puisque la ligne suivante n'est pas correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    set @type = exec('select geom_simpl.STGeometryN('+@idx+').STGeometryType() from Zone_VE')
    Je voudrais attribuer le résultat de la requête à la variable @type, comment puis-je faire ??...

  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Décrivez un peu plus votre besoin,ce que vous voulez obtenir avec un jeu d'essais et annotez votre code.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    Alors j'ai un champ geometry qui avec la fonction .AsText() s'affiche comme suit :

    GEOMETRYCOLLECTION (POINT (13.55157470703125...
    GEOMETRYCOLLECTION (POINT (-74.12109375 83.0...
    GEOMETRYCOLLECTION (POINT (140.9739685058593...
    GEOMETRYCOLLECTION (LINESTRING (59.375610351...
    GEOMETRYCOLLECTION (POINT (19.82496643066406...
    GEOMETRYCOLLECTION (POINT (-1.83583450317382...
    GEOMETRYCOLLECTION (POLYGON ((34.90316390991...
    GEOMETRYCOLLECTION (POINT (8.911651611328125...

    Ces GEOMETRYCOLLECTION contiennent des points, des polygones, des linestring, des multipolygones, des multilinestring.

    je veux supprimer tout mes éléments qui ne sont pas des polygones ou des multipolygones.

    Dans mon curseur je récupère le nombre d'éléments de chaque GEOMETRYCOLLECTION à l'aide de .STNumGeometries() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id_z_ve, Geom_simpl.STNumGeometries() FROM Zone_VE
    Je parcours tout les éléments de mes GEOMETRYCOLLECTION
    while @idx <= @idx_tot (limité à 5 dans mon précédent exemple).

    Cet élément sert à obtenir le type de Geometry de l'élément situé à l'indice (@idx) de ma geometrycollection .STGeometryType() : exec('select geom_simpl.STGeometryN('+@idx+').STGeometryType() from Zone_VE')

    je veux juste attribuer cette valeur (qui sera donc soit 'points' soit des 'polygones' soit des 'linestring' soit des 'multipolygones' soit des 'multilinestring')
    à une variable @type

    pour ensuite tester cette variable.

  10. #10
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Pas besoin de curseur. Vous pouvez faire cela en une seule requête UPDATE récursive.
    En gros, vous extrayez chaque géométrie partielle puis vous recomposez sans tenir compte de ce qui n'est pas polygone

    A lire sur les requêtes récursives : http://sqlpro.developpez.com/cours/s...te-recursives/

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Allez je vous donne la solution parce que là vous en êtes à l'âge de pierre au niveau des requêtes !

    Le jeu d'essais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    USE tempdb;
    GO
     
    CREATE TABLE T_GEO
    (GEO_ID   INT PRIMARY KEY,
     GEO      GEOMETRY);
    GO
     
    INSERT INTO T_GEO
    VALUES (1, 'GEOMETRYCOLLECTION(POINT(0 0), POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0)))'),
           (2, 'GEOMETRYCOLLECTION(POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0)))'),
           (3, 'GEOMETRYCOLLECTION(POINT(0 0))'),
           (4, 'GEOMETRYCOLLECTION(POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0)), POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)))'),
           (5, 'GEOMETRYCOLLECTION(POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0)), POLYGON ((10 10, 10 11, 11 11, 11 10, 10 10)))');
    GO
    La table des nombres (limitée à 10000) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE T (N INT)
    GO
    INSERT INTO T
    SELECT COALESCE(MAX(N) + 1, 1) FROM T
    GO 10000
    La requête qui fait tout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    WITH 
    T0 AS
    (
    -- éclatement de la géométrie en n sous géométries simples avec uniquement des polygones
    SELECT GEO_ID, N, GEO.STGeometryN(N) AS SIMPLE_GEO,
           ROW_NUMBER() OVER (PARTITION BY GEO_ID ORDER BY N) AS POS
    FROM   T_GEO
           INNER JOIN T
                 ON T.N BETWEEN 1 AND GEO.STNumGeometries()
    WHERE  GEO.STGeometryN(N).STDimension() = 2             
    ),
    T1 AS
    (
    -- concaténation récursive des polygones
    SELECT GEO_ID, SIMPLE_GEO, POS
    FROM   T0
    WHERE  POS = 1
    UNION  ALL
    SELECT T1.GEO_ID, T1.SIMPLE_GEO.STUnion(T2.SIMPLE_GEO), T2.POS
    FROM   T1
           INNER JOIN T0 AS T2
                 ON T1.GEO_ID = T2.GEO_ID
                 AND T1.POS = T2.POS-1),
    T3 AS
    (
    -- recherche des lignes ayant le plus de polygones
    SELECT GEO_ID, SIMPLE_GEO, 
           ROW_NUMBER() OVER (PARTITION BY GEO_ID ORDER BY POS DESC) AS N
    FROM   T1)
    -- solution
    SELECT GEO_ID, SIMPLE_GEO.STAsText()
    FROM   T3
    WHERE  N = 1
    Ce qui donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    GEO_ID      SIMPLE_GEO
    ----------- ----------------------------------------------------------------------------------------
    1           POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0))
    2           POLYGON ((0 0, 1 1, 2 2, 3 3, 3 0, 0 0))
    4           POLYGON ((0 0, 1 0, 3 0, 3 3, 2 2, 1 1, 0 1, 0 0))
    5           MULTIPOLYGON (((10 10, 11 10, 11 11, 10 11, 10 10)), ((0 0, 3 0, 3 3, 2 2, 1 1, 0 0)))

    Dans votre cas, remplacez le SELECT final par un UPDATE !

    A +

    PS : ayez au moins la décence d'acheter mon livre pour apprendre le SQL ! ;-)
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 21
    Points : 13
    Points
    13
    Par défaut
    Merci pour la solution! Hum Hum évidemment je ne comprend pas tout, loin de là, s'est embêtant et même dommage !

    Enfin je crois que je vais m'en sortir...

    Il faut éviter d'utiliser les curseurs ???

Discussions similaires

  1. [SQL Server]Problème avec l'authentification SQL SERVER
    Par tidou dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 20/04/2005, 15h40
  2. Fonction sous SQL Server
    Par GeffD dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 08/04/2005, 11h32
  3. fonction DATEADD [SQL SERVER]
    Par HULK dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/12/2004, 17h33
  4. Problème d'installation de sql server 2000
    Par michelci dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 12/12/2003, 08h02
  5. problème de float sur SQL server 2000.
    Par fidji dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 24/07/2003, 14h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo