2

I have a problem with a Postgres query and can't find a solution in stackexchange or any SQL Documentation.

I have two tables in PostGIS, one for streets and one for house-numbers. I now want to find the closest given house number to a certain street (for an address search).

In a sub-query I calculated the distance, selected the street name and the number as well as the coordinates. In the where clause I tried to filter the data for the minimal distance. I addressed the subquery with its alias, but get the error that the "relation is not defined", although I just defined it. Any simple solution for that problem?

SELECT * FROM
(SELECT ST_Distance(ha.geom, sn.geom) AS cp
 , sn.nam AS name
 , ha.hnr AS nr
 , ST_AsText(ST_Transform(ha.geom,4326)) AS pt
FROM hausnummern_be AS ha, strassen_be AS sn
WHERE ha.hnr = '1' AND sn.nam LIKE 'Samariter%'
ORDER BY cp ASC) AS xy
WHERE cp = (SELECT min(cp) FROM xy);
2
  • The error 'relation is not defined' is often a problem with the table name. Check for typos, and if it's not in the public schema, you'll need to add schema.tablename, so in your case, 'schema.hausnummern_be'.
    – Matt
    Commented Dec 1, 2016 at 9:37
  • Hi Matt, thank you for your comments. For testing reasons I have all my tables in the public schema. I forgot to write that the non defined relation is just the alias "xy" which I gave the sub-query. The error occurs in the last row. But there is possibly a solution making the query "DISTINCT ON"... Commented Dec 1, 2016 at 9:49

1 Answer 1

3

You can only reference xy if it were a CTE. The reason is because it's born at the same time as you main query.

So for reference you'd have to do do this:

   WITH xy AS( (SELECT ST_Distance(ha.geom, sn.geom) AS cp
 , sn.nam AS name
 , ha.hnr AS nr
 , ST_AsText(ST_Transform(ha.geom,4326)) AS pt
FROM hausnummern_be AS ha, strassen_be AS sn
WHERE ha.hnr = '1' AND sn.nam LIKE 'Samariter%'
ORDER BY cp ASC)
SELECT * 
    FROM xy
     WHERE cp = (SELECT min(cp) FROM xy);

But as you said, this is probably not best way to solve this problem. DISTINCT ON would be better.

DISTINCT ON solution there are many one is KNN, but I'll post the version that works on most PostgreSQL and PostGIS. The ST_DWithin significantly speeds things up if you want to scale this to more than one search. Replace 10 with some value you feel that searching any further distance is unlikely to find an answer. e.g. I say a house should be no more than 50 units from it's closest street. The bigger you make it the slower, but safer you'll be.

  SELECT DISTINCT ON (ha.hnr)  ST_Distance(ha.geom, sn.geom) AS cp
, sn.nam AS name
, ha.hnr AS nr
, ST_AsText(ST_Transform(ha.geom,4326)) AS pt
 FROM hausnummern_be AS ha INNER JOIN strassen_be AS sn
      ST_DWithin(ha.geom, sn.geom, 50)
  WHERE ha.hnr = '1' AND sn.nam LIKE 'Samariter%'
     ORDER BY ha.hnr, cp ASC;
1
  • Thank you very much.. Also for the tip with ST_DWithin... Yes, my idea is to address this query via php from a website, so it should be fast. Commented Dec 1, 2016 at 13:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.