Using SAP HANA Spatial, how do I query for all the points contained within a circle? Ideally, I would like to specify the latitude and longitude of the center, as well as the radius.
For instance, select all landmarks around 'Berlin - Alexanderplatz' (52.5219184 13.4132147) in a radius of 10 kilometers.
PS. To try it out:
Register an account on https://account.hanatrial.ondemand.com and log in.
Create a Database: Open Databases & Systems under Persistence. Click New, enter a Database ID, select HANA MDC (<trial>) as Database System, enter a SYSTEM User Password, and save.
Open the Development Tools: In the overview of your database, click SAP HANA Web-based Development Workbench and log in with the SYSTEM user. Under Security, grant the application privilege sap.hana.ide::Catalog to the user SYSTEM. (Yes I know, don't do this in real life!). Open the Catalog.
Create a database table: Click the button Open SQL Console (Command-Alt-C), enter the following SQL code and click the Run (F8) button.
CREATE COLUMN TABLE "COORDINATES" ("LOCATION_NAME" VARCHAR(100), "COORDINATE" ST_POINT(0) CS_POINT);
INSERT INTO "COORDINATES" VALUES ('Berlin - Brandenburger Tor', NEW ST_Point('POINT(52.5162746 13.377704)'));
INSERT INTO "COORDINATES" VALUES ('Berlin - Gendarmenmarkt', NEW ST_Point('POINT(52.5137224 13.3926698)'));
INSERT INTO "COORDINATES" VALUES ('Paris - Tour Eiffel', NEW ST_Point('POINT(48.8583701 2.2944813)'));
To query by rectangle, fire the following statement.
SELECT LOCATION_NAME, COORDINATE.ST_ASGEOJSON() FROM COORDINATES WHERE (NEW ST_Polygon('Polygon((52 13, 52 14, 53 14, 53 13, 52 13))').ST_Contains(COORDINATE)) = 1;
But, remember, I need a circle! How can I retrieve the same results?
Wouldn't that be the case that the distance between your circle center point and your objects need to be smaller than the radius?
Something like
SELECT LOCATION_NAME, COORDINATE.ST_ASGEOJSON()
FROM COORDINATES
WHERE
COORDINATE.ST_Distance( NEW ST_Point('POINT(52.5162746 13.377704)')) <= 2;
Here I just put the coordinates for the Brandenburger Tor and the radius of 2 - but you should get the picture.
Related
I'm building a report in Power BI and could setup a Power Query custom column using Text.Contains to solve this problem but the M Code would be very long and I'd rather perform this upstream in the SQL query. I have very little SQL experience.
I'm working with website data from Adobe Analytics. We have our website URLS and web pages grouped into categorical segments based on the product/service the URL/webpage corresponds to. A segment is defined by a list of URL paths and/or web page names, sometimes 1 path/page, sometimes over 30.
My result needs to be the following table:
Page URL Path
Page Name
Page Category
varchar(255)
varchar(255)
varchar(255)
Page URL Path examples:
/careers/starting-your-career/scholarships.html
/services/technology/ecommerce.html
Corresponding Page Name Examples:
Career & Scholarships | Company Name
Digital Transformation | E-Commerce | Company Name
There are a total of 76 page categories/segments to define. This screenshot shows an example of some categories and their definition.
Can anyone help me get started in writing this query?
I tried using CONTAINS but I believe this only works within a WHERE statement and I don't think it can be scaled to the needed extent:
SELECT
post_evar3 as 'Page URL Path',
post_evar4 as 'Page Name',
CASE
WHEN post_evar3 CONTAINS ('/services/assurance' or 'services/audit' or 'insights/financial-reporting')
AND (post_evar3 CONTAINS 'asc-842' OR post_evar4 CONTAINS 'asc 842')
THEN 'Audit Services'
WHEN post_evar3 CONTAINS '/services/strategy-and-management-consulting'
THEN 'Business Stratgegy Operations'
ELSE 'Other'
END AS 'Page Category'
FROM
Marketing.WebAnalytics.WebData
WHERE
exclude_hit = 0
AND hit_source = 1
I've read about Full-Text Search and Index solutions that are over my head in developing and I don't know that this method can be used within the Power BI SQL query environment. I've wondered if I need to declare the definition values into their own table, then join with the WebData table, though defining using both Page URL Path AND Page Name for the same category throws me for a loop.
The M code for this kind of matching is not large, though execution time can can vary
let BufferedTable2=Table.Buffer(Table2),
Source = Table.AddColumn(Table1,"Match",(i)=>try Table.SelectRows( BufferedTable2, each Text.Contains(i[Column1],[Match1], Comparer.OrdinalIgnoreCase) and Text.Contains(i[Column2],[Match2], Comparer.OrdinalIgnoreCase) ) [Return]{0} otherwise null, type text)
in Source
I set up a PostGIS database that I added in GeoServer via a parameterized SQL view. I use Leaflet to display this layer via WMS.
I would like to limit the number of features I see in the bounding box (5 maximum in my case). I tried to add a LIMIT 5 at the end of my SQL view but it affects the number of features on the whole map not in the bouding box.
Here is a simplified example to illustrate the issue. The aim is to get the 5 most populated cities located in the bounding box. It would work if Geoserver made this query :
SELECT geometry FROM table_cities
WHERE geometry && ST_GeomFromText(
'POLYGON ((-5.185 41.954, -5.185 51.374, 23.378 51.374, 23.378 41.954, -5.185 41.954))',
4326)
ORDER BY population LIMIT 5
But instead it wraps the SQL view inside a new SELECT dedicated to keep only the features located in the bounding box:
SELECT geometry FROM
(SELECT geometry FROM table_cities ORDER BY population LIMIT 5)
WHERE geometry && ST_GeomFromText(
'POLYGON ((-5.185 41.954, -5.185 51.374, 23.378 51.374, 23.378 41.954, -5.185 41.954))',
4326)
Is there a way to force Geoserver to put the bouding box verification before the LIMIT 5 selection?
Or maybe there is a different method to achieve what I want ?
You can add the Geoserver Where Clause placeholder :where_clause:
Because an and is automatically/systematically added, you must already have a where clause, even if it is a dummy 1=1 clause that always evaluate to true.
SELECT geometry
FROM table_cities
WHERE 1 = 1 :where_clause:
ORDER BY population
LIMIT 5
Note the absence of and between the 1=1 and :where_clause:
I have this statement that is generated by Geoserver
SELECT
shape AS shape
FROM
(
SELECT
c.chantier_id id,
sdo_geom.sdo_buffer(c.shape, m.diminfo, 1) shape,
c.datedebut datedebut,
c.datefin datefin,
o.nom operation,
c.brouillon brouillon,
e.code etat,
u.utilisateur_id utilisateur,
u.groupe_id groupe
FROM
user_sdo_geom_metadata m, lyv_chantier c
JOIN lyv_utilisateur u ON c.createur_id = u.utilisateur_id
JOIN lyv_etat e ON c.etat_id = e.etat_id
JOIN lyv_operation o ON c.operation = o.id
WHERE
m.table_name = 'LYV_CHANTIER'
AND m.column_name = 'SHAPE'
) vtable
WHERE
( brouillon = 0
AND ( etat != 'archive'
OR etat IS NULL )
AND sdo_filter(shape, mdsys.sdo_geometry(2003, 4326, NULL, mdsys.sdo_elem_info_array(1, 1003, 1), mdsys.sdo_ordinate_array(
2.23365783691406, 48.665657043457, 2.23365783691406, 48.9341354370117, 2.76649475097656, 48.9341354370117, 2.76649475097656, 48.665657043457, 2.23365783691406, 48.665657043457)), 'mask=anyinteract querytype=WINDOW') = 'TRUE' );
On my local instance (dockerized if that can explain anything) it works fine, but on another instance I get an error :
ORA-13226: interface not supported without a spatial index
I guess that the SDO_FILTER is applied to the result of SDO_BUFFER which is therefore not indexed.
But why is it working on my local instance ?!
Is there some kind of weird configuration shenanigan that could explain the different behavior maybe ?
EDIT : The idea behind this is to get around a bug in Geoserver with Oracle databases where it renders only the first point of MultiPoint geometries, but works fine with MutltiPolygon.
I am using a SQL view as layer in Geoserver (hence the subselect I guess).
First, you need to do some debugging here.
Connect to each instance, on the same user as your Geoserver's datasource, and run the sql. From the same connections (in each instance) you must also verify that the user's metadata view (user_sdo_geom_metadata) have an entry for the table and the table has a spatial index - whose owner is the same user as the one you connect.
Also, your query ( select ... from 'vtable') has a column 'shape' which is a buffer of the column lyv_chantier.shape. The sdo_filter, in this sql, expects a spatial index on the vtable.shape - which cannot exist. You should try to use a different alias (e.g. buf_shape) and sdo_filter(buf_shape,...) - to see if the sql fails in both instances, as it should.
I'm in a bit of a hurry right now, so my instructions are summarized. If you want, do this debugging and post the results. We then can go into details.
EDIT: Judging from your efforts, I'd say that the simplest approach is: 1) add a second geometry column to lyv_chantier (e.g. buf_shp). 2) update lyv_chantier set buf_shp = sdo_geom.sdo_buffer(shape,...). 3) insert into user_sdo_geom_metadata the values (lyv_chantier, buf_shp, ...). 4) create a spatial index on column buf_shp. You may need to consider a trigger to update buf_shp whenever shape changes...
This is a very practical approach but you don't provide any info about your case (what is the oracle version, how many rows does the table have, how is it used, why do you want to use sdo_buffer, etc), so that's my recommendation for now.
Also, since you are, most likely, using an sql view as layer in Geoserver (you don't say anything about that, either), you could also consider using pure GS functionality to achieve your goal.
At the end, without describing your goal, it's difficult to provide anything more tailor-made.
I'm trying to spatialise a table of 400 polygons (MapInfo tab layer) all of which are adjacent to each other into a SQL Server 2012 database. There are no polygons within polygons etc.
I want one row per polygon but I can only generate one row for all 400. I have the WKT and a sample of the code I'm using is:
select geometry::STGeomFromText('MULTIPOLYGON( ((319621.99946835
110837.002493295, 319640.501385461 110850.59860145, 319695.199120806
110879.700271183, 319728.303041127 110879.300385649, 319752.898058391
110876.501186912, 319767.401120868 110872.702274339, 319786.199860179
110873.60201679, 319789.102121686 110887.897924629, 319792.103323927
110898.504888418, 319794.29651018 110916.299794679, 319812.699486557
110940.202952471, 319621.99946835 110837.002493295)),
((319910.700282805 110880.699985018, 319916.900568753
110861.595453633, 319941.602771812 110838.00220713, 319973.601853945
110866.004191645, 320000.002539591 110899.404630869, 320025.999217243
110931.295502202, 320034.301993772 110944.001865043, 320038.696611339
110948.600548684, 319910.700282805 110880.699985018)))', 4326)
I hope I don't have to do this 400 times!
select geometry::STGeomFromText('POLYGON((319621.99946835
110837.002493295, 319640.501385461 110850.59860145, 319695.199120806
110879.700271183, 319728.303041127 110879.300385649, 319752.898058391
110876.501186912, 319767.401120868 110872.702274339, 319786.199860179
110873.60201679, 319789.102121686 110887.897924629, 319792.103323927
110898.504888418, 319794.29651018 110916.299794679, 319812.699486557
110940.202952471, 319621.99946835 110837.002493295))', 4326)
select geometry::STGeomFromText('POLYGON((319910.700282805
110880.699985018, 319916.900568753 110861.595453633, 319941.602771812
110838.00220713, 319973.601853945 110866.004191645, 320000.002539591
110899.404630869, 320025.999217243 110931.295502202, 320034.301993772
110944.001865043, 320038.696611339 110948.600548684, 319910.700282805
110880.699985018))', 4326)
Currently the data is in a SQL Server 2005 database but we are migrating to SQL Server 2012 soon.
In the future, the business will make changes to only certain sections of the layer and then I would hope to just spatialise those changes.
As spatial functions are not native to SQL Server 2005 stack, I have SpatialWare from MapInfo that did this for me via it's EasyLoader utility but in SQL Server 2012, because the spatial functions are now native, MapInfo is only spatialising the centroids of the polygons. Otherwise this would be the easiest and preferred option.
If anyone could tell me how I can use MapInfo to spatialise the table so I get all 400 rows or alternativley, the correct SQL, I'd be most grateful.
My customer want to have a "Slide Show" of all the "Dashboards" that are in the CRM. He wants to be able to hang a TV out and then show a slide with some "Dashboards" that will change every 10 seconds. The data needs to be up to date, so taking screenshots and putting them in a Powerpoint isn't enough. I was thinking about the following :
Create a custom Page with an Iframe and update the iframe every 10 seconds with a new "Dashboard" in it. I know you can do the following => /OrganizationName/dashboards/dashboard.aspx?dashboardId=%7b16a69a12-105a-e011-bd7f-000c29198df7%7d&dashboardType=1030&pagemode=iframe, but there is no way where I can find the ID. "The Copy A Link" functionality when "Right"-clicking on a view isn't there anymore.
I remember at the "Tech Days" of CRM, that there was a possiblity to immediatly connect to the "Report"-server for showing the "Dashboards"... Or is there a table in the "Database" who has all the "Names" + "IDs" of the dashboards?? I can't seem to find it in the Database...
How would you guys make a cool "Dashboard"-slid for on TV (PC connected to TV is what I mean by that).
I have a few screens in my office building showing dashboards from CRM, mainly Service Desk/call centre statistics.
I used this 'copy link' method to obtain a URL to the full screen dashboard (without any sidebars) then I installed a plugin/extension for IE to auto-refresh and cycle through various dashboard tabs (can't remember what it's called, but if you Google I'm sure you'll find it). This is always up to date and creates a slideshow effect.
System Dashboards are System Forms and Personal Dashboards are User Forms so it cab be retrieved from dbo.SystemFormBase and dbo.UserFormBase tables respectively.
If any Personal dashboard is shared then that details can be retrieved from PrincipalObjectAccess table.
Use below sp to retrieve dashboard id, name and type for the specific user.
Create PROCEDURE [dbo].[GetDashboardIds]
(
#SystemUserID uniqueidentifier
)
AS
BEGIN
select FormId as 'DashboardID',Name as 'Name', 'System' as DashboardType
from dbo.SystemFormBase
where Type = 0
Union
select UserFormId as 'DashboardID',Name as 'Name', 'Custom' as DashboardType
from dbo.UserFormBase
where Type = 0 and OwnerId = #systemUserID
union
select UserFormId as 'DashboardID',Name as 'Name', 'Custom' as DashboardType
from dbo.UserFormBase UFB inner join PrincipalObjectAccess POA on UFB.UserFormId = ObjectId
where Type = 0 and POA.PrincipalId = #systemUserID
end
Happy Coding