Insert GEOMETRY value using PostgreSQL 9.3 - postgresql

I want to insert GEOMETRY values into a table. For which I have a table with three columns as shown below:
Table: geo
create table geo
(
p1 float,
p2 float,
Paths GEOMETRY
);
Input values: I have following values
p1 = 22.9901232886963
p2 = 87.5953903123242
In SQL Server I used this:
INSERT INTO geo(Paths)
VALUES (geometry = geometry::STGeomFromText('POINT (22.9901232886963 87.5953903123242)'
,4326);
Question: Is there any function of GEOMETRY to calculate points in PostgreSQL 9.3 version?

This works for me by referring: http://www.postgresql.org/docs/current/static/functions-geometry.html.
The function:
point(point(double precision, double precision);
So I need to convert the function: using ::geometry
Finally the insert statement looks like:
insert into geo values(22.9901232886963 87.5953903123242,
point(22.9901232886963 87.5953903123242)::geometry);
Am I right?

Related

Indexing issue in postgres

It is impossible to speed up the database due to indexing.
I create a table:
CREATE TABLE IF NOT EXISTS coordinate( Id serial primary key,
Lat DECIMAL(9,6),
Lon DECIMAL(9,6));
After that I add indexing:
CREATE INDEX indeLat ON coordinate(Lat);
CREATE INDEX indeLon ON coordinate(Lon);
Then the table is filled in:
INSERT INTO coordinate (Lat, Lon) VALUES(48.685444, 44.474254);
Fill in 100k random coordinates.
Now I need to return all coordinates that are included in a radius of N km from a given coordinate.
SELECT id, Lat, Lon
FROM coordinate
WHERE acos(sin(radians(48.704578))*sin(radians(Lat)) + cos(radians(48.704578))*cos(radians(Lat))*cos(radians(Lon)-radians(44.507112))) * 6371 < 50;
The test execution time is approximately 0.2 seconds, and if you do not do CREATE INDEX, the time does not change. I suspect that there is an error in the request, maybe you need to rebuild it somehow?
I'm sorry for my english
An index can only be used if the indexed expression is exactly what you have on the non-constant side of the operator. That is obviously not the case here.
For operations like this, you need to use the PostGIS extension. Then you can define a table like:
CREATE TABLE coordinate (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
p geography NOT NULL
);
and query like this:
SELECT id, p
FROM coordinate
WHERE ST_DWithin(p, 'POINT(48.704578 44.507112)'::geography, 50);
This index would speed up the query:
CREATE INDEX ON coordinate USING gist (p);

Store circles in Postgres geometry field

Ideally it would be something like this, but WKT doesn't have circle type.
ST_GeomFromText('CIRCLE(10 20, 10)',4326)
Although, circle type is listed among geometric types,
circle <(x,y),r> (center point and radius)
I wonder if it's possible to use circle type directly in sql:
update <table>
set the_geom = circle '((10, 20),10)'::geometry
where id = <id>;
But it says SQL Error [42846]: ERROR: cannot cast type circle to geometry.
Using ST_Buffer for storing circles is a kludge so I don't want to use it.
Alternative solution could be jsonb + geojson, but it doesn't support circles either.
UPD: There is my table structure. Currently I'm using longitude/latitude/radius, but I'd like to use either geo_json or the_geom. How could GeoJSON and WKT not support a circle?
CREATE SEQUENCE my_table_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
CREATE TABLE my_table (
id INT NOT NULL,
longitude NUMERIC(10, 7) DEFAULT NULL,
latitude NUMERIC(10, 7) DEFAULT NULL,
radius INT DEFAULT NULL,
geo_json JSONB,
the_geom Geometry DEFAULT NULL, PRIMARY KEY(id)
);
Circle is native for postgresql as you can see on the manual documentation.
Geometry is a type related to PostGis Extension, and doesnt have CIRCLE but use polygons with lot of points instead.
Function starting with ST_ are also Postgis functions and work only with Postgis geometry or geography data type
SQL DEMO:
create table points ( p POINT not null);
create table lines ( l LINE not null);
create table circles ( c CIRCLE not null);
insert into points (p) values ( POINT(1.2, 123.1) );
insert into lines (l) values ( LINE(POINT(1.2, 123.1), POINT(-5, -123)) );
insert into circles (c) values ( CIRCLE(POINT(1.2, 123.1), 10) );
SELECT * FROM points;
SELECT * FROM lines;
SELECT * FROM circles;
The GIST index allows you to work efficiently with circles. If that's the only thing you intend to store in this table, then you can do it like this:
CREATE TABLE my_table (
id INT NOT NULL,
longitude NUMERIC(10, 7) DEFAULT NULL,
latitude NUMERIC(10, 7) DEFAULT NULL,
radius INT DEFAULT NULL,
geo_json JSONB
);
CREATE INDEX idx_my_table ON my_table USING GIST ( circle( point( latitude, longitude ), radius ));
As others have pointed out, you cannot mix this table with GEOMETRY types, which are incompatible.
In order to utilize the index above, you must express your WHERE criteria in similar terms: circle( point( latitude, longitude ), radius ) or '<( latitude, longitude ), radius >'::circle and use the operators that GIST knows about ... which are listed below. I'm aware that projecting the Euclidian shape of a circle onto a non-Euclidian spherical geometry has limitations, but for index purposes it should work OK with care.
https://www.postgresql.org/docs/current/gist-builtin-opclasses.html

Postgis nearest coordinates

I'm trying to make a REST service that returns a list of places ordered by distance from the user coordinate. I found this query using postgis:
SELECT *
FROM your_table
ORDER BY your_table.geom <-> "your location..."
LIMIT 5;
But I'm not able to apply this to my actual database. I have a table that contains these columns:
title, address, description, latitude, longitude
all these values as Strings.
I'll be very happy if someone help me. Thx!
I dont know why, but ORDER BY <-> isnt exact. Sometime the closest link is on the 3rd position. So I get 101 element and then use distance to selected the closest one.
CREATE OR REPLACE FUNCTION map.get_near_link(
x numeric,
y numeric)
RETURNS TABLE(Link_ID int, distance int) AS
$BODY$
DECLARE
strPoint text;
BEGIN
strPoint = 'POINT('|| X || ' ' || Y || ')';
With CTE AS (
SELECT Link_ID,
TRUNC(ST_Distance(ST_GeomFromText(strPoint,4326), geom )*100000)::integer as distance
FROM map.vzla_seg S
ORDER BY
geom <-> ST_GeomFromText(strPoint, 4326)
LIMIT 101
)
SELECT *
FROM CTE
ORDER BY distance
LIMIT 5
In order to use PostGIS you have to enable the extension in the database. Ideally, you just run the CREATE EXTENSION postgis; command and it works. NOTE form the install page: DO NOT INSTALL it in the database called postgres. For more information visit the site.
Adding a geometry column (spatial data can be stored in this type of columns) to your table:
SELECT AddGeometryColumn(
'your_schema',
'your_table',
'geom', -- name of the column
4326, -- SRID, for GPS coordinates you can use this, for more information https://en.wikipedia.org/wiki/Spatial_reference_system
'POINT', -- type of geometry eg. POINT, POLYGON etc.
2 -- number of dimension (2 xy - 3 xyz)
);
UPDATE yourtable t SET t.geom = ST_SetSRID(ST_MakePoint(t.x, t.y), 4326)
-- the x and y is the latitude and longitude
Now you can use spatial queries on your table like this:
SELECT
*
FROM
your_table
ORDER BY
your_table.geom <-> ST_SetSRID(ST_MakePoint(x, y), 4326)
LIMIT 5;
NOTE: as others mentioned, below PostgreSQL 9.5 <-> isn't always reliable.

How to make a GIS query on PostgreSQL without use ST_X("Position4326") function

I have written this geographical query:
SELECT
ST_X("Position4326") AS lon,
ST_Y("Position4326") AS lat,
"Values"[4] AS ppe,
"Values"[5] AS speed
FROM
(
SELECT
*
FROM
"SingleData"
UNION ALL
SELECT
*
FROM
"SingleDataOld"
) AS d
WHERE
"Values"[5] > 0
and its work.
But I would like to select a specific area in the database, e.g.:
Lat_min = 43.77;
Lat_max = 43.88;
Lon_min = 12.95;
Lon_max = 13.05;
to reduce the time of working.
It is possible do this without use ST_X and ST_Y function? Or, better: I would like use a WHERE clause, but the format of geographical data are Position4326, an alphanumeric string that I do not know how manipulate.
The format of position4326 could be of geometry type or geography type. Postgis offer a big range of functions which you can use to limit the result data improve the performance.
I.e. use can the function ST_MakeEnvelope and the && operator:
WHERE ...
AND Position4326 && ST_MakeEnvelope(xmin, ymin, xmax, ymax, srid);
in latitude/longitude terms, the arguments are so:
ST_MakeEnvelope(long_min, lat_min, long_max, lat_max, srid);
Because you column is named Position4326, I guess you should use srid = 4326.
ST_MakeEnvelope(12.95, 43.77, 13.05, 43.88, 4326);
Also ensure that you have a spatial index on the column Position4326:
CREATE INDEX Position4326_gix ON your_table USING GIST (Position4326);

function st_intersects() does not exist using PostgreSQL 9.3

I have a table as shown below with three columns.
Table: geomet
create table geomet
(
cola float,
colb float,
geopath geometry
);
Insertion of records:
insert into geomet values('12.32232442','43.2324535',point(12.32232442,43.2324535)::geometry);
I have this:
select * from geomet;
cola colb geopath
---------------------------------------------------------------------
12.32232442 43.2324535 01010000004F34D5B407A528409D2B4A09C19D4540
Note: I need to find the Intersect of column geopath in my table as shown above. I have also installed PostGIS.
So I have tried this:
Try 1:
SELECT ST_Intersects(geopath) from geomet;
Got an error:
ERROR: function st_intersects(geometry) does not exist
Try 2:
SELECT ST_Intersects(cola,colb) from geomet;
Got an error:
ERROR: function st_intersects(double precision, double precision) does not exist
ST_Intersects requires two geometries or two geometry fields, as you are checking for the intersection between one geometry and another or one set and another set.
SELECT ST_Intersects(geomA, geomB) FROM some_table;
or
SELECT a.id., b.id, ST_Intersects(a.geom, b.geom)
FROM table a, table b
WHERE a.id > b.id;
will give you all the pairwise intersection between two tables. Obviously, you can use ST_Intersects in a where clause in a similar fashion, to only return rows where the records from two different tables intersect.