Find closest Store SQL - sql

Output of what I would like to get
This is what I'd like to get to:
I have a Table which holds my store locations and their long and lat in three columns, and another table which holds my customer key their long and lat. in my output id like to see a column with closest store and a column with distance to the closest store.
Thank you so much for your help!

For future readers, I found how to do it:
1) DECLARE #start_location GEOGRAPHY = GEOGRAPHY::Point(Lat,Long,4326)
2) SELECT ID, #start_location.STDistance(Location)/1609.344 [YourTableName] from (SELECT ID, GEOGRAPHY::Point(Latitude, Longitude, 4326) as Location FROM [TheTableWhereYourZipInfoIsStored]
notes: /1609.344 is because you want to convert to miles from meters.

Related

Fastest way to filter latitude and longitude from a sql table?

I have a huge table data where sample data is like below. I want to filter few latitude and longitude records from the huge table and I am using In clause to filter list of lat,lon values but when I try to run the query it takes more a min to execute what is the better query to execute it faster? the list of lat,lon is around 120-150
id longitude latitude
--------------------------
190 -0.410123 51.88409
191 -0.413256 51.84567
query:-
SELECT DISTINCT id, longitude, latitude
FROM geo_table
WHERE ROUND(longitude::numeric, 3) IN (-0.418, -0.417, -0.417, -0.416 and so on )
AND ROUND(latitude::numeric, 3) IN (51.884, 51.884, 51.883, 51.883 and so on);
If at least one of the ranges of values in X or Y is tight you can try prefiltering rows. For example, if X (longitude) values are all close together you could try:
SELECT distinct id,longitude,latitude
from (
select *
FROM geo_table
where longitude between -0.418 and -0.416 -- prefilter with index scan
and latitude between 51.883 and 51.884 -- prefilter with index filter
) x
-- now the re-check logic for exact filtering
where ROUND(longitude::numeric,3) in (-0.418, -0.417, -0.417, -0.416, ...)
and ROUND(latitude::numeric,3) in (51.884, 51.884, 51.883, 51.883, ...)
You would need an index with the form:
create index ix1 on geo_table (longitude, latitude);
First, the way you are looking for a list of latitudes and a list of longitudes is likely wrong if you are looking for points locations:
point: lat;long
----------------
Point A: 1;10
Point B: 2;10
Point C: 1;20
Point D: 2;20
--> if you search for latitude in (1;2) and longitude in (10;20), the query will return the 4 points, while if you search for (latitude,longitude) in ((1;10),(2;20)), the query will return only points A and D.
Then, since you are looking for rounded values, you must index the rounded values:
create index latlong_rdn on geo_table (round(longitude,3),round(latitude,3));
and the query should use the exact same expression:
select *
from geo_table
where (round(longitude,3),round(latitude,3)) in
(
(-0.413,51.846),
(-0.410,51.890)
);
But here again rounding is not necessarily the best approach when dealing with locations. You may want to have a look at the PostGIS extension, to save the points as geography, add a spatial index, and to search for points within a distance (st_dwithin()) of the input locations.

Get centroid coordinates of a given country in BigQuery

In BigQuery, given a country in ISO-2 code I need to get its centroids coordinates (lat and long).
There is a way to do this?
Looking into the geography functions of BQ I did not find a way.
You can use the bigquery-public-data.geo_openstreetmap.planet_features table from BigQuery public datasets to calculate the centroids of countries. The inner query is based on this answer from Stack Overflow. Consider the below query and output.
SELECT -- Extract country code, lat and long
CountryISO2Code,
ST_X(centroid) AS longitude,
ST_Y(centroid) AS latitude
FROM (SELECT (SELECT value FROM UNNEST(all_tags)
WHERE key = 'ISO3166-1:alpha2') AS CountryISO2Code,
ST_CENTROID(geometry) centroid -- calculate the centroid with the geometry values
FROM `bigquery-public-data.geo_openstreetmap.planet_features`
WHERE EXISTS (SELECT 1 FROM UNNEST(all_tags) WHERE key='boundary' AND value= 'administrative')
AND EXISTS (SELECT 1 FROM UNNEST(all_tags) WHERE key='admin_level' AND value = '2')
AND EXISTS (SELECT 1 FROM UNNEST(all_tags) WHERE key='ISO3166-1:alpha2'))
WHERE CountryISO2Code="IN" -- country code to filter the output
Output of the above query
Please note that there are some country codes that are not available in the table. Also, OSM dataset in BigQuery itself is produced as a public good by volunteers, and there are no guarantees about data quality.
I also found some community-maintained data from Github like this one which can be imported into BigQuery and is ready-to-use.

Find a POINT( , ) within a Polygon BigQuery 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

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)

Find if decimal lat and long falls with a particular range in access

I have 2 tables, one with columns id, date/time, latitude and longitude. The other table has columns company id, latitude and longitude. The lat and longs are in decimals in both tables.
How would I take the lat and longs in table 1 and see if they are within .0005 of a company in table 2 and then return the company name? The query I am using is a sub query that can be found below.
Any help would be appreciated, thank you.
It would be something like:
Select
Table1.*
From
Table1,
Table2
Where
Abs(Table1.Latitude - Table2.Latitude) < 0.0005
And
Abs(Table1.Longitude - Table2.Longitude) < 0.0005
Expand the Where clause to filter on one company only, if that is your task.
Then either this company (success) or an empty recordset (failure) would be returned.