How to find city name from latitude and longitude in Postgresql? - sql

I have a database which has latitudes and longitudes of various properties stored. I want to find out, which city does each of these properties belong to (all properties are in the US).

Talking about Postgresql, first of all you need to get a data of US cities boundaries shape file. Possible sites are
https://www.census.gov/geo/maps-data/data/tiger.html
https://www.census.gov/geo/maps-data/data/tiger-cart-boundary.html
https://catalog.data.gov/dataset?tags=cities
After that import data into postgres. I am assuming that your properties data is already stored in postgres. Make sure the SRID geometry type of cities boundaries is 4326. if not, you can convert it easily with ST_transform function.
Finally, to check which city some specific lat/long falls in, you need to convert the lat/long into point geometry and check against the cities data. e.g it would be some thing like this
SELECT c.city_name FROM cities_boundaries AS c, properties AS p
WHERE ST_CONTAINS(c.geom, ST_SetSRID(ST_MakePoint(p.longitude, p.latitude), 4326))

Related

Difference between Geometry and Geometry collections

Please can anyone explain the difference between
$table->geometry('positions'); and $table->geometryCollection('positions'); in laravel.
I'm assuming your database is MySQL. Please add it as a tag to your post then.
According to the manual:
https://dev.mysql.com/doc/refman/5.7/en/spatial-type-overview.html
Some spatial data types hold single geometry values:
GEOMETRY
GEOMETRY can store geometry values of any type. The other single-value types (POINT, LINESTRING, and POLYGON) restrict their values to a particular geometry type.
and
The other spatial data types hold collections of values:
GEOMETRYCOLLECTION
GEOMETRYCOLLECTION can store a collection of objects of any type. The other collection types (MULTIPOINT, MULTILINESTRING, and MULTIPOLYGON) restrict collection members to those having a particular geometry type.
The difference is that the last one can hold multiple entities (coordinates/points) in a single column. This is useful if you want to save a square shape for instance, which needs 4 points.
A practical example for the first one would be a location (which is a single set of coordinates (lat+lng)).
I sadly cant give you much information on how to use them within Laravel. However in raw SQL, it basically looks like this:
-- Add data to a GEOMETRY column
SET #g = 'POINT(1 1)';
INSERT INTO geo VALUES (ST_GeomFromText(#g));
-- Add data to a GEOMETRYCOLLECTION column
SET #g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geocol VALUES (ST_GeomFromText(#g));

what field type should we give for longitude and latitude columns in flask models to create table in postgresql?

I wanted to create a database table in Flask which consists of longitude and latitude fields in table?So what should be the field types for those?
Depending on your database type, you'll probably want a numeric type that supports decimals. PostgreSQL supports double precision, which you can use like so:
from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION
or
db = SQLAlchemy()
db.DOUBLE_PRECISION
Keep in mind that you're prone to floating point errors with decimals, so when you want to know whether latitude/longitude values have changed, it may be smart to round them to a specific number of decimals and/or use numpy.isclose to compare the old and new values

Storing and querying location (coords) in PostgreSQL

In my user schema I have a location column which will hold the last updated coordinates of the user. Is there a PostgreSQL data type I could use to allow me to run SQL queries to search, for example something like: SELECT username FROM Users WHERE currentLocation="20 Miles Away From $1"
If your "location" column holds GPS coordinates then basically your only option is to use the PostGIS extension. With PostGIS you store your locations in a column with geometry or geography data type and then you can apply a rich set of function on it. Your query would become something like:
SELECT username
FROM users
WHERE ST_Distance(currentlocation, $1) = 20; -- careful with units
This is assuming that $1 is of the same data type as currentlocation. You probably have to convert the miles to kilometers, depending on your coordinate reference system and the data type (geography would produce kilometers, geometryproduces whatever unit the data is in).

How to convert XY coordinates to GPS in Oracle Spatial?

I'm querying an SDO_GEOMETRY field to return a given point in a shape, and I would like to get the GPS coordinates for that point. My query is as follows:
select
sdo_lrs.locate_pt(sdo_lrs.convert_to_lrs_geom(shape),0.02).sdo_ordinates
from
TEST_SCHEMA.TEST_TABLE
where
route='ABC'
and
segmentnum='101.1'
This returns an SDO_ORDINATE_ARRAY like so:
MDSYS.SDO_ORDINATE_ARRAY(100000.203621556,999999.57084293,0.02)
How do I convert the first two elements of the SDO_ORDINATE_ARRAY into GPS coordinates? I haven't been able to find anything in the Oracle Spatial documentation related to a function that would accomplish this.
It turns out you have to transform the coordinate system of the shape before it's passed to convert_to_lrs_geom(), using sdo_cs.transform(). In this case the SRID is 8307 (thanks to jim mcnamara for pointing out that the SRID was the issue), so the SQL to return the correct coordinates is:
select
sdo_lrs.locate_pt(sdo_lrs.convert_to_lrs_geom(sdo_cs.transform(shape,8307)),0.02).sdo_ordinates
from
TEST_SCHEMA.TEST_TABLE
where
route='ABC'
and
segmentnum='101.1'

Convert Shapefile to SQL

I'm trying to convert a shapefile I have to SQL format.
I've tried doing this using shp2pgsql, but, alas, this program doesn't read the SHAPEFILE.prj file, so I end up with coordinates in an inconvenient format.
Is there a way to convert shapefiles to SQL which respects their PRJ specification?
You may have things in one projection that you want to display or interact with in more familiar values, like longitude and latitude. For example Planet OpenStreetMap uses a spherical mercator and gives you values like this when you ask for text:
cal_osm=# select st_astext(way) from planet_osm_point limit 3;
st_astext
-------------------------------------------
POINT(-13852634.6464924 4928686.75004766)
POINT(-13850470.0501262 4930555.55031171)
POINT(-13850160.8268447 4930880.61375574)
(3 rows)
You can use st_transform to return a more familiar format like this:
cal_osm=# select st_astext(st_transform(way, 4326)) from planet_osm_point limit 3;
st_astext
-------------------------------------------
POINT(-124.440334282677 40.4304093953086)
POINT(-124.42088938268 40.4431868953078)
POINT(-124.418111582681 40.4454091953076)
(3 rows)
A prj file is essentially a text file that contains the coordinate system information in the ESRI Well-known-text(WKT) format. Could you just write a program that uses shp2pgsql to convert the geometries and then store the associated WKT string from the prj?
Of note: The WKT format is an EPSG accepted format for delimiting projected and geographic coordinate system information, but different authorities may have different names for projections or projection parameters. PostGIS might be different from Oracle which might in turn be different from ESRI. So if you store the prj's WKT make sure that it is in an esri_coordinate_system column. PostGIS might have a different naming convention format for parameters.
Also, in case you're interested, there is a C++ open FileGDB api that allows you to access row information without license. It's available in 32 and 64 bit on windows and linux:
http://resources.arcgis.com/content/geodatabases/10.0/file-gdb-api