How to get lat long from HEXEWKB PostGis? - postgresql

I'm making query and want get from this format points again. Is this possible? How i can do it?
UPDATE geo2 SET geometry = ST_AsHEXEWKB(ST_GeomFromText('POLYGON((-15.66486 27.91996,-15.60610 27.91820, -15.60359 27.97169, -15.66586 27.97144,-15.66486 27.91996))',4326)) where options->>'koatuu' = '0110392101' ;

Yes, It's possible. You should just cast it to a geometry type with:
SELECT ST_AsHEXEWKB(ST_GeomFromText('POLYGON((-15.66486 27.91996,-15.60610 27.91820, -15.60359 27.97169, -15.66586 27.97144,-15.66486 27.91996))',4326))::geometry FROM geo2 WHERE ....
and you can get lat/long by using ST_X, ST_Y
SELECT ST_X(your_column::geometry) as long, ST_Y(your_column::geometry) as lat FROM geo2

Related

How do I select a subset of columns with diesel-rs?

I am struggling for several hours now to query a subset of the available columns of a table as well as including a calculation in it. I know that it is not the best way to execute the calculation in the select query, but for now, I am just working on a prototype and it should be feasible for that.
I am using diesel-rs as a ORM for all my database actions in my back-end implementation. The data will be stored in a PostgresSQL server. The full table - as stored in the database - is created using the following query:
CREATE TABLE airports
(
id SERIAL PRIMARY KEY,
icao_code VARCHAR(4) NOT NULL UNIQUE, -- the official ICAO code of the airport
last_update TIMESTAMP NOT NULL, -- when were the information updated the last time?
country VARCHAR(2) NOT NULL, -- two letter country code
longitude REAL NOT NULL, -- with 6 decimal places
latitude REAL NOT NULL, -- with 6 decimal places
name VARCHAR NOT NULL -- just a human readable name of the airport
);
Running diesel migrations run generates the airports table definition and querying the database works without any issue.
Now I am trying to query a list of all airports (their ICAO code) with the corresponding coordinates as well as the distance to a supplied coordinate. Therefore, I created the following diesel-rs table! macro myself
table! {
airport_by_distance (icao_code) {
icao_code -> Varchar,
longitude -> Float8,
latitude -> Float8,
distance -> Float8,
}
}
as well as the struct corresponding to the diesel-rs definition:
#[derive(QueryableByName)]
#[table_name = "airport_by_distance"]
struct AirportByDistance {
icao_code: String,
longitude: f64,
latitude: f64,
distance: f64,
}
The following snipped - as of my understanding - should query the required information:
use diesel::dsl::sql_query;
let latitude = 4.000001;
let longitude = 47.000001;
let query_sql = format!("SELECT icao_code, longitude, latitude, (3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance FROM airports ORDER BY distance;", lat=latitude, long=longitude);
let result = match sql_query(query_sql).load::<AirportByDistance>(database_connection) {
Ok(result) => result,
Err(error) => {
error!("{:?}", error);
return Err(());
}
};
Unfortunately, executing the load method, results in a DeserializationError(Custom { kind: UnexpectedEof, error: "failed to fill whole buffer" }) error.
The query which was executed was:
SELECT icao_code,
longitude,
latitude,
(3959.0 * acos(cos(radians(4.000001)) * cos(radians(latitude)) * cos(radians(longitude) - radians(47.000001)) +
sin(radians(4.000001)) * sin(radians(latitude)))) AS distance
FROM airports
ORDER BY distance;
I took it and executed it manually, but it worked flawlessly. I even tried removing the calculation and just selecting a subset of columns, but with no luck either.
Right now I am not sure what I am doing wrong. How can I fix this issue?
EDIT with the fixed code: For the ones who are interested how to code would look like after using the helpful advice of Rasmus:
The table! macro is completely gone and the data definition struct looks like this:
#[derive(Queryable)]
struct AirportByDistance {
icao_code: String,
longitude: f32,
latitude: f32,
distance: f64,
}
The code for the querying the database is as follows:
let result = match airports.select(
(
icao_code,
longitude,
latitude,
sql::<Double>(
&format!("(3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance", lat=latitude_reference, long=longitude_reference)
)
)
).load::<AirportByDistance>(database_connection)
{
Ok(result) => result,
Err(error) => {
error!("{:?}", error);
return Err(());
}
};
for airport in result {
info!(
"AIRPORT: {} has {}nm distance",
airport.icao_code, airport.distance
);
}
I think the problem is that the deserializer don't know the raw types of the queried columns.
Try to use typed diesel names/values as much as possible, and explicit sql strings only where needed. And I don't think the "fake" table declaration airports_by_distance helps. Maybe something like this:
use diesel::sql_types::Double;
let result = a::airports
.select((
a::icao_code,
a::longitude,
a::latitude,
sql::<Double>(&format!("(3959.0 * acos(cos(radians({lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians({long})) + sin(radians({lat})) * sin(radians(latitude)))) AS distance", lat=latitude, long=longitue)
))
.load::<AirportByDistance>(&db)?
(Using the table! macro manually is basically just telling diesel that such a table will exist in the actual database when running the program. If that is not true, you will get runtime errors.)

User defined variable in postgresql query not working

Please can anyone help to solve the problem of the PostgreSQL query? It's expected to return the result in the image but it returns nothing:
Query:
SET foo.date_1 = '2021-01-04';
select interface_name, max(time_stamp) as date, message,api_request from central
where application = 'OMS to DW'
and time_stamp like ''''||'%' || current_setting('foo.date_1')||'%'||''''
and message not like 'succe%'
group by interface_name,message,api_request
Expecting:
Thank you all for trying to help. The problem now it's solved, the correct code should be:
SET foo.date_1 = '2021-01-04';
select interface_name, max(time_stamp) as date, message,api_request from central
where application = 'OMS to DW'
and time_stamp like '%' || current_setting('foo.date_1')||'%'
and message not like 'succe%'
group by interface_name,message,api_request

Postgis - Check if a Point is inside Polygon

I am trying to use the ST_Intersection function to intersect a point by city polyogn but I am having no luck (Hasura + Postgresql)
create table "public"."cities"(
geom geometry(MultiPolygon, 4326)
//other colmuns
);
then i added a row with multipolygon of my city :
INSERT INTO "public"."cities"
VALUES(ST_GeomFromText('MULTIPOLYGON(((
5.334 36.213,5.335 36.22,5.356 36.225,5.365 36.233,5.371 36.232,5.378 36.237,5.387 36.24,5.39 36.243,5.395 36.244,5.398 36.248,5.406 36.249,5.413 36.253,5.421 36.25,5.431 36.249,5.435 36.246,5.433 36.24,5.434 36.239,5.433 36.231,5.44 36.232,5.445 36.23,5.447 36.227,5.453 36.227,5.457 36.229,5.462 36.227,5.477 36.231,5.482 36.238,5.49 36.238,5.491 36.24,5.495 36.241,5.503 36.241,5.506 36.237,5.506 36.234,5.509 36.231,5.51 36.225,5.509 36.216,5.502 36.211,5.502 36.207,5.498 36.202,5.498 36.199,5.502 36.194,5.502 36.183,5.499 36.18,5.499 36.177,5.497 36.175,5.492 36.174,5.487 36.169,5.481 36.17,5.481 36.163,5.478 36.159,5.475 36.158,5.476 36.154,5.472 36.148,5.472 36.145,5.469 36.142,5.452 36.141,5.44 36.133,5.438 36.13,5.433 36.13,5.43 36.138,5.42 36.137,5.418 36.139,5.41 36.136,5.406 36.136,5.402 36.139,5.392 36.137,5.384 36.138,5.369 36.13,5.364 36.132,5.364 36.135,5.346 36.138,5.345 36.143,5.35 36.151,5.347 36.156,5.347 36.164,5.343 36.171,5.343 36.175,5.338 36.18,5.336 36.187,5.333 36.191,5.334 36.194,5.333 36.201,5.336 36.205,5.334 36.213
)))', 4326) );
But when i run this query with a Point is the center of city, i doesn't return any data.
select *
from "public"."cities"
where ST_Intersects("public"."cities"."geom", ST_GeometryFromText('POINT(36.1917 5.4235)', 4326));
UPDATE :
I stored the polygon in long-lat, but i was querying with lat-long Point, my mistake

Sphinx search with filtering by coordinates

I have this query:
select id, post_category_name , title, description,WEIGHT(),
geodist(50.95, 24.69, latitude, longitude) dist
from serv1 where match('#(title,description) searchText ) and dist < 2000000000000;
in my DB post have latitude: 50.85, and longitude: 24.69
In result I have distance:893641 but real distance is 11119.49 meters.
I also tried convert input coordinates to radians but still have not correct distance.
What I'm doing wrong? Thank you in advance.
Try
geodist(50.95, 24.69, latitude, longitude, {in=deg}) dist
(note {in=deg})
It returns the number close to the one you're expecting:
mysql> select geodist(50.95, 24.69, 50.85, 24.69, {in=deg});
+-----------------------------------------------+
| geodist(50.95, 24.69, 50.85, 24.69, {in=deg}) |
+-----------------------------------------------+
| 11124.928711 |
+-----------------------------------------------+
1 row in set (0.00 sec)
Based on code in one of your other questions, would do something like
sql_query = select p.id, ... , \
RADIANS(l.Latitude) as latitude, RADIANS(l.Longitude) as longitude FROM ...
using the MySQL function to convert the stored degreee value to radions for the attribute.
The...
sql_attr_float = latitude
sql_attr_float = longitude
would be unchanged.

How to write a conditional SELECT query in TSQL using arguments in the WHERE/AND clause?

I've got a stored procedure that returns postal codes within a specified radius. The arguments are
ALTER PROCEDURE [dbo].[proximitySearch]
#proximity int = 0,
#country varchar (2) = NULL,
#city varchar (180) = NULL,
#state varchar (100) = NULL,
#stateAbr varchar (2) = NULL,
#postalCode varchar(20) = NULL
AS...
In the proc, the first query needs to select a single record (or no record) that matches whatever was passed in and assign the lat/long to local variables, as I started to write below:
SELECT TOP 1 #Longitude = Longitude, #Latitude = Latitude
FROM PostalCodes
WHERE ...
This is where I get stumped... the WHERE clause needs to be conditional based on what was passed in. Some arguments (or all of them) can be NULL, and I don't want use them in the query if they are.
I was thinking along the lines of:
SELECT TOP 1 #Longitude = Longitude, #Latitude = Latitude
FROM PostalCodes
WHERE Longitude IS NOT NULL
AND CASE WHEN #postalCode IS NOT NULL THEN PostalCode = #postalCode ELSE 1 END
...but this doesn't work. How is something like this typically done? (I'm definitely not a seasoned TSQL guy!!!) Thanks in advance!
There is more than one way of implementing that kind of logic:
1)
SELECT TOP 1 #Longitude = Longitude, #Latitude = Latitude
FROM PostalCodes
WHERE Longitude IS NOT NULL
AND (#postalCode IS NULL OR PostalCode = #postalCode)
2)
SELECT TOP 1 #Longitude = Longitude, #Latitude = Latitude
FROM PostalCodes
WHERE Longitude IS NOT NULL
AND PostalCode = COALESCE(#postalCode, PostalCode)
SELECT TOP 1 #Longitude = Longitude, #Latitude = Latitude
FROM PostalCodes
WHERE
((#postalCode IS NULL) OR (PostalCode = #postalCode))
AND ((#someotherparam IS NULL) OR (someothercolumn = #someotherparam)) etc...
But be aware that this technique can suffer from 'parameter sniffing'