Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/workshop-foss4g/joins.rst

    r1 r62  
    11.. _joins: 
    22 
    3 Section 12: Spatial Joins 
    4 ========================= 
    5  
    6 Spatial joins are the bread-and-butter of spatial databases.  They allow you to combine information from different tables by using spatial relationships as the join key.  Much of what we think of as "standard GIS analysis" can be expressed as spatial joins. 
    7  
    8 In the previous section, we explored spatial relationships using a two-step process: first we extracted a subway station point for 'Broad St'; then, we used that point to ask further questions such as "what neighborhood is the 'Broad St' station in?" 
    9  
    10 Using a spatial join, we can answer the question in one step, retrieving information about the subway station and the neighborhood that contains it: 
    11  
    12 .. code-block:: sql 
    13  
    14   SELECT  
    15     subways.name AS subway_name,  
    16     neighborhoods.name AS neighborhood_name,  
     3Partie 12 : Les jointures spatiales 
     4=================================== 
     5 
     6Les jointures spatiales sont la cerise sur le gâteau des base de données spatiales. Elles vous pemettent de combiner les informations de plusieurs tables en utilisant une relation spatiale comme clause de jointure. La plupart des "analyses SIG standards" peuvent être exprimées à l'aide de jointures spatiales. 
     7 
     8Dans la partie précédente, nous avons utilisé les relations spatiales en utilisant deux étapes dans nos requêtes : nous avons dans un premier temps extrait la station de métro "Broad St" puis nous avons utilisé ce résultat dans nos autres requêtes pour répondre aux questions comme "dans quel quartier se situe la station 'Broad St' ?" 
     9 
     10En utilisant les jointures spatiales, nous pouvons répondre aux questions en une seule étape, récupérant les informations relatives à la station de métro et le quartier la contenant : 
     11 
     12.. code-block:: sql 
     13 
     14  SELECT 
     15    subways.name AS subway_name, 
     16    neighborhoods.name AS neighborhood_name, 
    1717    neighborhoods.boroname AS borough 
    1818  FROM nyc_neighborhoods AS neighborhoods 
     
    2121  WHERE subways.name = 'Broad St'; 
    2222 
    23 ::  
    24  
    25    subway_name | neighborhood_name  |  borough   
     23:: 
     24 
     25   subway_name | neighborhood_name  |  borough 
    2626  -------------+--------------------+----------- 
    2727   Broad St    | Financial District | Manhattan 
    2828 
    29 We could have joined every subway station to its containing neighborhood, but in this case we wanted information about just one.  Any function that provides a true/false relationship between two tables can be used to drive a spatial join, but the most commonly used ones are: :command:`ST_Intersects`, :command:`ST_Contains`, and :command:`ST_DWithin`. 
    30  
    31 Join and Summarize 
    32 ------------------ 
    33  
    34 The combination of a ``JOIN`` with a ``GROUP BY`` provides the kind of analysis that is usually done in a GIS system. 
    35  
    36 For example: **"What is the population and racial make-up of the neighborhoods of Manhattan?"** Here we have a question that combines information from about population from the census with the boundaries of neighborhoods, with a restriction to just one borough of Manhattan. 
    37  
    38 .. code-block:: sql 
    39  
    40   SELECT  
    41     neighborhoods.name AS neighborhood_name,  
     29Nous avons pu regrouper chaque station de métro avec le quartier auquel elle appartient, mais dans ce cas nous n'en voulions qu'une. Chaque fonction qui envoit un résultat du type vrai/faux peut être utilisée pour joindre spatialement deux tables, mais la plupart du temps on utilise : :command:`ST_Intersects`, :command:`ST_Contains`, et :command:`ST_DWithin`. 
     30 
     31Jointure et regroupement 
     32------------------------ 
     33 
     34La combinaison de ``JOIN`` avec ``GROUP BY`` fournit le type d'analyse qui est couramment utilisé dans les systÚmes SIG. 
     35 
     36Par exemple : **Quelle est la population et la répartition raciale du quartier de Manhattan ?** Ici nous avons une question qui combine les informations relatives à la population recensée et les contours des quartiers, or nous ne voulons qu'un seul quartier, celui de Manhattan. 
     37 
     38.. code-block:: sql 
     39 
     40  SELECT 
     41    neighborhoods.name AS neighborhood_name, 
    4242    Sum(census.popn_total) AS population, 
    4343    Round(100.0 * Sum(census.popn_white) / Sum(census.popn_total),1) AS white_pct, 
     
    5252:: 
    5353 
    54    neighborhood_name  | population | white_pct | black_pct  
     54   neighborhood_name  | population | white_pct | black_pct 
    5555 ---------------------+------------+-----------+----------- 
    5656  Carnegie Hill       |      19909 |      91.6 |       1.5 
     
    8484 
    8585 
    86 What's going on here? Notionally (the actual evaluation order is optimized under the covers by the database) this is what happens: 
    87  
    88 #. The ``JOIN`` clause creates a virtual table that includes columns from both the neighborhoods and census tables.  
    89 #. The ``WHERE`` clause filters our virtual table to just rows in Manhattan.  
    90 #. The remaining rows are grouped by the neighborhood name and fed through the aggregation function to :command:`Sum()` the population values. 
    91 #. After a little arithmetic and formatting (e.g., ``GROUP BY``, ``ORDER BY``) on the final numbers, our query spits out the percentages. 
    92  
    93 .. note::  
    94  
    95    The ``JOIN`` clause combines two ``FROM`` items.  By default, we are using an ``INNER JOIN``, but there are four other types of joins. For further information see the `join_type <http://www.postgresql.org/docs/8.1/interactive/sql-select.html>`_ definition in the PostgreSQL documentation. 
    96  
    97 We can also use distance tests as a join key, to create summarized "all items within a radius" queries. Let's explore the racial geography of New York using distance queries. 
    98  
    99 First, let's get the baseline racial make-up of the city. 
    100  
    101 .. code-block:: sql 
    102  
    103   SELECT  
    104     100.0 * Sum(popn_white) / Sum(popn_total) AS white_pct,  
    105     100.0 * Sum(popn_black) / Sum(popn_total) AS black_pct,  
     86Que ce passe-t-il ici ?  Voici ce qui se passe (l'ordre d'évaluation est optimisé par la base de données) : 
     87 
     88#. La clause ``JOIN`` crée une table virtuelle qui contient les colonnes à la fois des quartiers et des recensements (tables neighborhoods et census). 
     89#. La clause ``WHERE`` filtre la table virtuelle pour ne conserver que la ligne correspondant à Manhattan. 
     90#. Les lignes restantes sont regroupées par le nom du quartier et sont utilisées par la fonction d'agrégation : :command:`Sum()` pour réaliser la somme des valeurs de la population. 
     91#. AprÚs un peu d'arithmétique et de formatage (ex: ``GROUP BY``, ``ORDER BY``)) sur le nombres finaux, notre requête calcule les pourcentages. 
     92 
     93.. note:: 
     94 
     95   La clause ``JOIN`` combine deux parties ``FROM``.  Par défaut, nous utilisons un jointure du type :``INNER JOIN``, mais il existe quatres autres types de jointures. Pour de plus amples informations à ce sujet, consultez la partie `type_jointure <http://docs.postgresql.fr/9.1/sql-select.html>`_ de la page de la documentation officielle de PostgreSQL. 
     96 
     97Nous pouvons aussi utiliser le test de la distance dans notre clef de jointure, pour créer une regroupement de "tous les éléments dans un certain rayon". Essayons d'analyser la géographie raciale de New York en utilisant les requêtes de distance. 
     98 
     99PremiÚrement, essayons d'obtenir la répartition raciale de la ville. 
     100 
     101.. code-block:: sql 
     102 
     103  SELECT 
     104    100.0 * Sum(popn_white) / Sum(popn_total) AS white_pct, 
     105    100.0 * Sum(popn_black) / Sum(popn_total) AS black_pct, 
    106106    Sum(popn_total) AS popn_total 
    107107  FROM nyc_census_blocks; 
    108108 
    109 ::  
    110  
    111         white_pct      |      black_pct      | popn_total  
     109:: 
     110 
     111        white_pct      |      black_pct      | popn_total 
    112112  ---------------------+---------------------+------------ 
    113113   44.6586020115685295 | 26.5945063345703034 |    8008278 
    114114 
    115115 
    116 So, of the 8M people in New York, about 44% are "white" and 26% are "black".  
    117  
    118 Duke Ellington once sang that "You / must take the A-train / To / go to Sugar Hill way up in Harlem." As we saw earlier, Harlem has far and away the highest African-American population in Manhattan (80.5%). Is the same true of Duke's A-train? 
    119  
    120 First, note that the contents of the ``nyc_subway_stations`` table ``routes`` field is what we are interested in to find the A-train. The values in there are a little complex. 
     116Donc, 8M de personnes dans New York, environ 44% sont "blancs" et 26% sont "noirs". 
     117 
     118Duke Ellington chantait que "You / must take the A-train / To / go to Sugar Hill way up in Harlem." Comme nous l'avons vu précédemment, Harlem est de trÚs loin le quartier ou se trouve la plus grande concentration d'africains-américains de Manhattan (80.5%). Est-il toujours vrai qu'il faut prendre le train A dont Duke parlait dans sa chanson ? 
     119 
     120PremiÚrement, le contenu du champ ``routes`` de la table ``nyc_subway_stations`` va nous servir à récupérer le train A. Les valeurs de ce champs sont un peu complexes. 
    121121 
    122122.. code-block:: sql 
    123123 
    124124  SELECT DISTINCT routes FROM nyc_subway_stations; 
    125    
    126 ::  
     125 
     126:: 
    127127 
    128128 A,C,G 
     
    136136.. note:: 
    137137 
    138    The ``DISTINCT`` keyword eliminates duplicate rows from the result.  Without the ``DISTINCT`` keyword, the query above identifies 491 results instead of 73. 
    139     
    140 So to find the A-train, we will want any row in ``routes`` that has an 'A' in it. We can do this a number of ways, but today we will use the fact that :command:`strpos(routes,'A')` will return a non-zero number if 'A' is in the routes field. 
    141  
    142 .. code-block:: sql 
    143  
    144    SELECT DISTINCT routes  
    145    FROM nyc_subway_stations AS subways  
     138   Le mot clef ``DISTINCT`` permet d'éliminer les répétitions de lignes de notre résultat. Dans ce mot clef, notre requête renverrait 491 résultats au lieu de 73. 
     139 
     140Donc pour trouver le train A, nous allons demander toutes les lignes ayant pour ``routes`` la valeur 'A'. Nous pouvons faire cela de différentes maniÚres, mais nous utiliserons aujourd'hui le fait que la fonction :command:`strpos(routes,'A')` retourne un entier différent de 0 si la lettre 'A' se trouve dans la valeur du champ route. 
     141 
     142.. code-block:: sql 
     143 
     144   SELECT DISTINCT routes 
     145   FROM nyc_subway_stations AS subways 
    146146   WHERE strpos(subways.routes,'A') > 0; 
    147     
     147 
    148148:: 
    149149 
     
    157157  A,B,C,D 
    158158  A,C,E 
    159    
    160 Let's summarize the racial make-up of within 200 meters of the A-train line. 
    161  
    162 .. code-block:: sql 
    163  
    164   SELECT  
    165     100.0 * Sum(popn_white) / Sum(popn_total) AS white_pct,  
    166     100.0 * Sum(popn_black) / Sum(popn_total) AS black_pct,  
     159 
     160Essayons de regrouper la répartition raciale dans un rayon de 200 mÚtres de la ligne du train A. 
     161 
     162.. code-block:: sql 
     163 
     164  SELECT 
     165    100.0 * Sum(popn_white) / Sum(popn_total) AS white_pct, 
     166    100.0 * Sum(popn_black) / Sum(popn_total) AS black_pct, 
    167167    Sum(popn_total) AS popn_total 
    168168  FROM nyc_census_blocks AS census 
     
    173173:: 
    174174 
    175         white_pct      |      black_pct      | popn_total  
     175        white_pct      |      black_pct      | popn_total 
    176176  ---------------------+---------------------+------------ 
    177177   42.0805466940877366 | 23.0936148851067964 |     185259 
    178178 
    179 So the racial make-up along the A-train isn't radically different from the make-up of New York City as a whole.  
    180  
    181 Advanced Join 
    182 ------------- 
    183  
    184 In the last section we saw that the A-train didn't serve a population that differed much from the racial make-up of the rest of the city. Are there any trains that have a non-average racial make-up? 
    185  
    186 To answer that question, we'll add another join to our query, so that we can simultaneously calculate the make-up of many subway lines at once. To do that, we'll need to create a new table that enumerates all the lines we want to summarize. 
     179La répartition raciale le long de la ligne du train A n'est pas radicalement différente de la répartition générale de la ville de New York. 
     180 
     181Jointures avancées 
     182------------------ 
     183 
     184Dans la derniÚre partie nous avons vu que le train A n'est pas utilisé par des populations si éloignées de la répartition totale du reste de la ville. Y-a-t-il des trains qui passent par des parties de la ville qui ne sont pas dans la moyenne de la répartition raciale ? 
     185 
     186Pour répondre à cette question, nous ajouterons une nouvelle jointure à notre requête, de telle maniÚre que nous puissions calculer simultanément la répartition raciale de plusieurs lignes de métro à la fois. Pour faire ceci, nous créerons une table qui permettra d'énumérer toutes les lignes que nous voulons regrouper. 
    187187 
    188188.. code-block:: sql 
    189189 
    190190    CREATE TABLE subway_lines ( route char(1) ); 
    191     INSERT INTO subway_lines (route) VALUES  
     191    INSERT INTO subway_lines (route) VALUES 
    192192      ('A'),('B'),('C'),('D'),('E'),('F'),('G'), 
    193193      ('J'),('L'),('M'),('N'),('Q'),('R'),('S'), 
     
    195195      ('7'); 
    196196 
    197 Now we can join the table of subway lines onto our original query. 
    198  
    199 .. code-block:: sql 
    200  
    201     SELECT  
     197Maintenant nous pouvons joindre les tables des lignes de métro à notre requête précédente. 
     198 
     199.. code-block:: sql 
     200 
     201    SELECT 
    202202      lines.route, 
    203       Round(100.0 * Sum(popn_white) / Sum(popn_total), 1) AS white_pct,  
    204       Round(100.0 * Sum(popn_black) / Sum(popn_total), 1) AS black_pct,  
     203      Round(100.0 * Sum(popn_white) / Sum(popn_total), 1) AS white_pct, 
     204      Round(100.0 * Sum(popn_black) / Sum(popn_total), 1) AS black_pct, 
    205205      Sum(popn_total) AS popn_total 
    206206    FROM nyc_census_blocks AS census 
     
    214214:: 
    215215 
    216      route | white_pct | black_pct | popn_total  
     216     route | white_pct | black_pct | popn_total 
    217217    -------+-----------+-----------+------------ 
    218218     S     |      30.1 |      59.5 |      32730 
     
    239239 
    240240 
    241 As before, the joins create a virtual table of all the possible combinations available within the constraints of the ``JOIN ON`` restrictions, and those rows are then fed into a ``GROUP`` summary. The spatial magic is in the ``ST_DWithin`` function, that ensures only census blocks close to the appropriate subway stations are included in the calculation. 
    242  
    243 Function List 
    244 ------------- 
    245  
    246 `ST_Contains(geometry A, geometry B) <http://postgis.org/docs/ST_Contains.html>`_: Returns true if and only if no points of B lie in the exterior of A, and at least one point of the interior of B lies in the interior of A. 
    247  
    248 `ST_DWithin(geometry A, geometry B, radius) <http://postgis.org/docs/ST_DWithin.html>`_: Returns true if the geometries are within the specified distance of one another.  
    249  
    250 `ST_Intersects(geometry A, geometry B) <http://postgis.org/docs/ST_Intersects.html>`_: Returns TRUE if the Geometries/Geography "spatially intersect" - (share any portion of space) and FALSE if they don't (they are Disjoint).  
    251  
    252 `round(v numeric, s integer) <http://www.postgresql.org/docs/7.4/interactive/functions-math.html>`_: PostgreSQL math function that rounds to s decimal places 
    253  
    254 `strpos(string, substring) <http://www.postgresql.org/docs/current/static/functions-string.html>`_: PostgreSQL string function that returns an integer location of a specified substring. 
    255  
    256 `sum(expression) <http://www.postgresql.org/docs/8.2/static/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE>`_: PostgreSQL aggregate function that returns the sum of records in a set of records. 
    257  
    258 .. rubric:: Footnotes 
     241Comme précédemment, les jointures créent une table virtuelle de toutes les combinaisons possibles et disponibles à l'aide des contraintes de type ``JOIN ON`. Ces lignes sont ensuite utilisées dans le regroupement ``GROUP``. La magie spatiale tient dans l'utilisation de la fonction ``ST_DWithin`` qui s'assure que les blocs sont suffisamment proches des lignes de métros incluses dans le calcul. 
     242 
     243Liste de fonctions 
     244------------------ 
     245 
     246`ST_Contains(geometry A, geometry B) <http://postgis.org/docs/ST_Contains.html>`_: retourne TRUE si et seulement si aucun point de B est à l'extérieur de A, et si au moins un point à l'intérieur de B  est à l'intérieur de A. 
     247 
     248`ST_DWithin(geometry A, geometry B, radius) <http://postgis.org/docs/ST_DWithin.html>`_: retourne TRUE si les géométries sont distantes du rayon donné. 
     249 
     250`ST_Intersects(geometry A, geometry B) <http://postgis.org/docs/ST_Intersects.html>`_: retourne TRUE si les géométries/géographies "s'intersectent spatialement" (partage une portion de l'espace) et FALSE sinon (elles sont disjointes). 
     251 
     252`round(v numeric, s integer) <http://www.postgresql.org/docs/7.4/interactive/functions-math.html>`_: fonction de PostgreSQL qui arrondit à s décimales. 
     253 
     254`strpos(chaîne, sous-chaîne) <http://www.postgresql.org/docs/current/static/functions-string.html>`_: fonction de chaîne de caractÚres de PostgreSQL qui retourne la position de la sous-chaine. 
     255 
     256`sum(expression) <http://www.postgresql.org/docs/8.2/static/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE>`_: fonction d'agrégation de PostgreSQL qui retourne la somme d'un ensemble de valeurs. 
     257 
     258.. rubric:: Notes de bas de page 
    259259 
    260260.. [#PostGIS_Doco] http://postgis.org/documentation/manual-1.5/ 
Note: See TracChangeset for help on using the changeset viewer.