<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html;
      charset=ISO-8859-1">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    <br>
    <br>
    <br>
    <meta http-equiv="content-type" content="text/html;
      charset=ISO-8859-1">
    Hello,<br>
    Let's cut to the chase: I need to select,<b> for each residential
      building</b> in my table  <b>that has say at least 2 pharmacies
      and 2 education centers</b> within a radius of X km, all POIs
    (pharmacies, comercial centres, medical centers, education centers,
    police stations, fire stations) which are within X km of the
    respective building. <br>
    <br>
    table structure-><br>
    <br>
    building (<br>
    id serial, <br>
    name varchar )<br>
    <br>
    poi_category(<br>
    id serial, <br>
    cname varchar) --cname being the category name of course<br>
    <br>
    poi(<br>
    id serial, <br>
    name varchar,<br>
     c_id integer)-- c_id is the FK referencing poi_category(id)<br>
    <br>
    so the structure would be : building, poi >----- poi_category<br>
    <br>
    <b>all coordinate columns are of type geometry</b> not geography (<u>let's

      call them geom</u>)<br>
    <br>
    here's the way i thought it should be done but i'm not sure it's
    even correct let alone the optimal solution to this problem<br>
    <br>
        SELECT r.id_b, r.id_p<br>
        FROM (<br>
             SELECT b.id AS id_b, p.id AS id_p, pc.id AS id_pc,pc.cname<br>
             FROM building AS b, poi AS p, poi_category AS pc<br>
             WHERE ST_DWithin(b.geom,p.geom, 1000) AND p.c_id=pc.id  --
    ST_DWithin (a,b, x) makes sure the distance between a & b is
    less or equal than x<br>
             ) AS r,<br>
             (<br>
             SELECT * FROM r GROUP BY id_b<br>
             ) AS r1<br>
    <br>
         HAVING  count (<br>
                           SELECT *<br>
                           FROM r, r1<br>
                           WHERE r1.id_b=r.id_b AND r.id_pc='pharmacy'<br>
    <br>
                        )>1<br>
                     AND<br>
                     count (<br>
                           SELECT *<br>
                           FROM r, r1<br>
                           WHERE r1.id_b=r.id_b AND r.id_pc='ed. centre'<br>
    <br>
                        )>1<br>
    <br>
    Is this the way to go for what i need ? What solution would be
    better from a performance point of view? What about the most elegant
    solution?<br>
    <br>
    Problem posted here also: 
    <a moz-do-not-send="true" class="moz-txt-link-freetext"
href="http://gis.stackexchange.com/questions/11445/postgis-advanced-selection-query">http://gis.stackexchange.com/questions/11445/postgis-advanced-selection-query</a><br>
     but i received an answer that seems wrong or not optimal at the
    very least<br>
    <br>
    And an example table that shows distances between :<br>
          -- Ed. centers have poi.c_id  3 and and pharmacies have
    poi.c_id 1<br>
    building.id   1    1    1    1    1    1    1    1    1    2    2   
    2    2    2    2    2    2    2    3    3    3    3    3    3    3   
    3    3    4    4    4    4    4    4    4    4    4    5    5   
    5    5    5    5    5    5    5<br>
    poi.id           1    2    3    4    5    6    7    8    9    1   
    2    3    4    5    6    7    8    9    1    2    3    4    5    6
       7    8    9    1    2    3    4    5    6    7    8    9    1   
    2    3    4    5    6    7    8    9<br>
    poi.c_id       1    3    1    2    3    4    1    2    3    1   
    3    1    2    3    4    1    2    3    1    3    1    2    3   
    4    1    2    3    1    3    1    2    3    4    1    2    3   
    1    3    1    2    3    4    1    2    3<br>
    distances   <b>10</b> <u>26</u>  <b>14</b>  15 <u>60</u>  28  <b>65</b> 
    49  <u>46</u>  <b>23</b> <u>54</u> <b>27</b>   16 <u>15</u> 
    48  <b>26</b>  47 <u>22</u> <b>19</b>  <u>11</u>   <b>55 </b>
    34 <u>53</u>  15  <b>31</b>  58  <u>39</u> <b>19</b>  <u>36</u> 
    <b>92</b>  47  <u>16</u> 30  <b>25</b>  59  <u>25</u>  <b>35</b> 
    <u>23</u> <b>21</b> 40 <u>51</u> 13   <b>43</b>  45  <u>42</u><br>
    between<br>
    building<br>
    and poi <br>
    (i have also decorated the distances depending on wether they are
    for a pharmacy (bold) or an ed. center (underlined) )      <br>
              <br>
    and the resulting table and the logic : I am looking for the
    buildings that have at least 2 pharmacies and 2 ed.centers within 30
    respectively 25 distance units (DU)<br>
    So  building 1 has  2 pharmacies within 30 DU but only one ed.
    center within 25 DU<br>
    building 2 has  3 pharmacies within 30 DU and  two  ed. centers 
    within 25 DU<br>
    building 3 has  only 1 pharmacy within 30 DU so the rest doesn't
    matter<br>
    building 4 has  2 pharmacies within 30 DU and  two  ed. centers 
    within 25 DU ( one of them is exactly 25 DU away)<br>
    building 5 has  1 pharmacies within 30 DU , we don't care about the
    rest <br>
    <br>
    The resulting table would then be:<br>
    building.id   2    2    2    2    2    2    2    2    2    4    4   
    4    4    4    4    4    4    4   <br>
    poi.id           1    2    3    4    5    6    7    8    9    1   
    2    3    4    5    6    7    8    9    <br>
    poi.c_id       1    3    1    2    3    4    1    2    3    1   
    3    1    2    3    4    1    2    3    <br>
    distances  <b></b> <b>23</b> <u>54</u>   <b>27</b> 16 <u>15</u> 
    48  <b>26</b>  47 <u>22</u>  <b>19</b>  <u>36</u>  <b>92</b> 
    47  <u>16</u> 30  <b>25</b>  59  <u>25</u>  <b></b>-- without
    the distances column which i'm just printing to make it easier to
    understand the results<br>
    between<br>
    <br>
    <br>
    <br>
      Do help a fellow postgres user ;;)<br>
    <br>
  </body>
</html>