Find a POINT( , ) within a Polygon BigQuery SQL - sql

I have two tables, one is a neighborhood table that lists the name of the neighborhood as well as neighborhood polygon with the format GEOGRAPHY.
In my second table I have the location data of a number of trees, including lattitude and longitude as FLOAT64 data types - I can convert these to a geography point using ST_GEOGPOINT.
What I am looking to do, is use the Lat and long from the trees table, and write a query that will return the name of the neighborhood of the cooresponding polygon that the point falls within
Any help is very appreciated

I found the solution via a join!
SELECT
t.tree_id,
t.species,
t.address,
t.plant_type,
st_geogpoint(longitude, latitude) as point,
nh.neighborhood
FROM `bigquery-public-data.san_francisco_trees.street_trees` AS t
JOIN `bigquery-public-data.san_francisco_neighborhoods.boundaries` AS nh
ON ST_WITHIN(st_geogpoint(t.longitude, t.latitude), nh.neighborhood_geom)
where longitude IS NOT NULL and latitude IS NOT NULL

Related

How to find distance between two points using latitude and longitude

I have a ROUTES table which has columns SOURCE_AIRPORT and DESTINATION_AIRPORT and describes a particular route that an airplane would take to get from one to the other.
I have an AIRPORTS table which has columns LATITUDE and LONGITUDE which describes an airports geographic position.
I can join the two tables using columns which they both share called SOURCE_AIRPORT_ID and DESTINATION_AIRPORT_ID in the routes table, and called IATA in the airports table (a 3 letter code to represent an airport such as LHR for London Heathrow).
My question is, how can I write an SQL query using all of this information to find, for example, the longest route out of a particular airport such as LHR?
I believe I have to join the two tables, and for every row in the routes table where the source airport is LHR, look at the destination airport's latitude and longitude, calculate how far away that is from LHR, save that as a field called "distance", and then order the data by the highest distance first. But in terms of SQL syntax i'm at a loss.
This would have probably been a better question for the Mathematics Stack Exchange, but I’ll provide some insight here. If you are relatively farmiliar with trigonometry, I’m sure you could understand the implementation given this resource: https://en.m.wikipedia.org/wiki/Haversine_formula. You are looking to compute the distance between two point on the surface of a sphere in terms of their distance across its surface (not a straight line, you can’t travel through the Earth).
The page displays this formula:
https://wikimedia.org/api/rest_v1/media/math/render/svg/a65dbbde43ff45bacd2505fcf32b44fc7dcd8cc0
Where
• φ1, φ2 are the latitude of point 1 and latitude of point 2 (in radians),
• λ1, λ2 are the longitude of point 1 and longitude of point 2 (in radians).

If you data is in degrees, you can simply convert to radians by multiplying by pi/180
There is a formula called great circle distance to calculate distance between two points. You probably can load is as a library for your operating system. Forget the haversine, our planet is not a perfect sphere.
If you use this value often, save it in your routes table.
I think you're about 90% there in terms of the solution method. I'll add in some additional detail regarding a potential SQL query to get your answer. So there's 2 steps you need to do to calculate the distances - step 1 is to create a table containing joining the ROUTES table to the AIRPORTS table to get the latitude/longitude for both the SOURCE_AIRPORT and DESTINATION_AIRPORT on the route. This might look something like this:
SELECT t1.*, CONVERT(FLOAT, t2.LATITUDE) AS SOURCE_LAT, CONVERT(FLOAT, t2.LONGITUDE) AS SOURCE_LONG, CONVERT(FLOAT, t3.LATITUDE) AS DEST_LAT, CONVERT(FLOAT, t3.LONGITUDE) AS DEST_LONG, 0.00 AS DISTANCE_CALC
INTO ROUTE_CALCULATIONS
FROM ROUTES t1 LEFT OUTER JOIN AIRPORTS t2 ON t1.SOURCE_AIRPORT_ID = t2.IATA
LEFT OUTER JOIN AIRPORTS t3 ON t1.DESTINATION_AIRPORT_ID = t3.IATA;
The resulting output should create a new table titled ROUTE_CALCULATIONS made up of all the ROUTES columns, the longitude/latitude for both the SOURCE and DESTINATION airports, and a placeholder DISTANCE_CALC column with a value of 0.
Step 2 is calculating the distance. This should be a relatively straightforward calculation and update.
UPDATE ROUTE_CALCULATIONS
SET DISTANCE_CALC = 2 * 3961 * asin(sqrt((sin(radians((DEST_LAT- SOURCE_LAT) / 2))) ^ 2 + cos(radians(SOURCE_LAT)) * cos(radians(DEST_LAT)) * (sin(radians((DEST_LONG- SOURCE_LONG) / 2))) ^ 2))
And that should give the calculated distance in the DISTANCE_CALC table for all routes seen in the data. From there you should be able to do whatever distance-related route analysis you want.

get city name by latitude and longitude from OSM data stored in Postgres

i know there are lot of similar question but after long time searchin none of them worked for me thats why i'm posting,
I want to get city name with lat and lon from planet_osm_polygon table where are polygons stored including polygons of cities, here is my code:
SELECT name
FROM planet_osm_polygon
where place = 'city'
and ST_CONTAINS(ST_Transform(way,4326), ST_SetSRID(ST_Point(41.693459100461496,44.8014495),4326));
(the logic is.. if polygon contains given point, return its name if its a city)
What is the problem? i transformed both geometries to 4326 but still not working. P.S "way" is a column of geometry(polygon).
Query always returns empty result
Edit
City is not missing from planet_osm_polygon and its geometry column really is type of polygon, here is some query results:
I believe you're switching x and y in your coordinate pairs. WGS84 expects longitude, latitude, not the other way around:
SELECT name
FROM planet_osm_polygon
WHERE place = 'city'
AND ST_Contains(ST_Transform(way,4326), ST_SetSRID(ST_MakePoint(44.80,41.69),4326));
On a side note: Consider reducing the precision of your coordinates. With so many decimal numbers you're entering the microscopy realm -> 41.693459100461496
Sample data
CREATE TEMPORARY TABLE planet_osm_polygon (name TEXT, way GEOMETRY,place TEXT);
INSERT INTO planet_osm_polygon
VALUES ('Georgia',ST_SetSRID('POLYGON((43.87 42.22,45.43 42.22,45.43 41.50,43.87 41.50,43.87 42.22))'::GEOMETRY,4289),'city');
The coordinates correspond to the following BBOX in the SRS 4289:
Query - point inside the BBOX, setting either BBOX and given point to WGS84
SELECT name
FROM planet_osm_polygon
WHERE place = 'city'
AND ST_Contains(ST_Transform(way,4326), ST_SetSRID(ST_MakePoint(44.80,41.69),4326));
name
---------
Georgia
(1 Zeile)

How can I return all the rows in a PostgreSQL/PostGIS table within a radius of Xkm provided by a longitude and latitude value?

I'm trying to have a go at learning about PostgreSQL and in particular, it's PostGIS extension and the benefits with regards to geographic spatial features it provides. I've loaded a PostgreSQL DB with a table that contains 30,000 records of latitude, longitude and a price value (for houses) and I want to start querying the DB to return all the rows that would be in a radius of Xkm of a particular latitude and longitude.
I've hit a brick wall as to how I might run this type of query as I've found the documentation to be quite limited online and I've found no similar attempts at this method of querying online.
Some methods I've tried:
SELECT *
FROM house_prices
WHERE ST_DWithin( ST_MakePoint(53.3348279,-6.269547099999954)) <= radius_mi *
1609.34;
This prompts the following error:
ERROR: function st_dwithin(geometry) does not exist
Another attempt:
SELECT * FROM house_prices ST_DWithin( 53.3348279, -6.269547099999954, 5); <-- A latitude value, longitude value and 5 miles radius
This prompts the following error:
ERROR: syntax error at or near "53.3348279"
Could anyone point me in the right direction/ know of some documentation I could look at?
** Edit **
Structure and set up of database and table in pgAdmin4
The first query has an invalid number of parameters. The function ST_DWithin expects at least two geometries and the srid distance,
and optionally a Boolean parameter indicating the usage of a spheroid (see documentation).
The second query is missing a WHERE clause and has the same problem as the first query.
Example from documentation:
SELECT s.gid, s.school_name
FROM schools s
LEFT JOIN hospitals h ON ST_DWithin(s.the_geom, h.the_geom, 3000)
WHERE h.gid IS NULL;
Perhaps something like this would be what you want to achieve:
SELECT *
FROM house_prices h
WHERE ST_DWithin(ST_MakePoint(53.3348,-6.2695),h.geom,h.radius_mi * 1609.34)
Also pay attention to the order of the coordinates pair (x,y or y,x), otherwise you might easily land on the sea with these coordinates ;-)
EDIT: Taking into account that there is no geometry on the table, so the points are stored in two different columns, longitude and latitude:
SELECT *
FROM house_prices
WHERE ST_DWithin(ST_MakePoint(longitude,latitude),ST_MakePoint(53.3348,-6.2695),1609.34)

POSTGRESQL - Polygon function for geolocations

I have 2 tables User_places where I can see for each user their home location defined by 2 separate attributes: longitude and latitude.
And I have second table Neighborhoods with attribute 'Area', that defines each neighborhood as polygon - jsonb format - "[{"latitude":XXXXX,"longitude":YYYYY},{"latitude":ZZZZZ,"longitude":AAAAA},{"latitude":BBBBBB,"longitude":CCCCC},{"latitude":DDDDD,"longitude":EEEEE}]".
Does anybody know how to check whether particular user lives in given neighborhood in Postgresql?
SELECT
user_id,
ST_Contains(
ST_GeomFromText(
(select
replace(replace(replace(replace(replace(area::text,']','))'),'[','POLYGON(('),'}', ''),',"longitude":',' '),'{"latitude":','')
from neighbourhoods
limit 1), 4326)
(ST_SetSRID(ST_MakePoint(latitude, longitude),4326))
) as polygon_check
from user_places
I will assume you have Postgis installed on your copy of postgresql? As this has all the Geometry and geographical function extensions to postgresql.
You could use ST_Contains to check if a point is contained in a given polygon, this returns a boolean.
select ST_Contains(neigbourhood.polygon,User_place.geom)
If you don't have a geom point value in the User_places table then this can be created using the ST_SetSRID function and ST_MakePoint function.
For example - SELECT ST_SetSRID(ST_MakePoint(LAT, LON),SRID);
where SRID is the reference for the projection you are using for example 4326 for WGS 84 `
I would recommend in postgresql make sure all of your Geographical tables have geoms in them, as it makes comparisons much easier.
For reference a good place to get answers for geographic and geometry database based questions is https://gis.stackexchange.com/

Incorrect Distances When Comparing geography values in SQL

I have a SQL database set up containing a number of fields one of which is a geography field called Coordinates. I have a need to search for all rows that are within a certain radius and to do that I am using the query
DECLARE #CurrentLocation geography;
SET #CurrentLocation = geography::Point(-84.505562, 39.137706, 4326)
SELECT * , Coordinates.STDistance(#CurrentLocation) AS Distance FROM tParkingLot
WHERE Coordinates.STDistance(#CurrentLocation )<= 200000
which gives me the following results
the first row is returning as expected as I used those coordinates as my center. However, when measuring the other two lots on google maps I find that the results should be closer to 1133.246 for row 2 and 74673.56 for row 3
I can see from other stackoverflow results that a common mistake is to insert data as lat/lon as opposed to lon/lat however I have already made and corrected that mistake and I cannot determine why I am getting distance results that are so far off from the actual measurements.
The cause of the problem is the order of latitude and longitude. Geography world traditionally uses (lat, lon) order, SQL world defined (x, y) order, which usually means (lon, lat) order.
Microsoft SQL Server Point constructor made confusing compromise: they use (x, y) order for Geometry, but (lat, lon) order for Geography:
Point ( Lat, Long, SRID ) [1]
Since your points are in Cincinnati rather than Antartica, swap argument order.
[1] https://learn.microsoft.com/en-us/sql/t-sql/spatial-geography/point-geography-data-type?view=sql-server-2017