How to perform STIntersect between a polygon and point geometryfile? - sql-server

What I have so far:
select Metro.Object_ID
from Geocoding_tab.dbo.Part1_Part2_Combined_Final as paypal
,Object_id.dbo.All_Combined_9_Metros as Metro
where paypal.geom.STIntersect(Metro.GEOM) = 1;

You can amend the query to use JOIN syntax
SELECT Metro.Object_ID
FROM
Geocoding_tab.dbo.Part1_Part2_Combined_Final as paypal
INNER JOIN
Object_id.dbo.All_Combined_9_Metros as Metro ON paypal.geom.STIntersects(Metro.GEOM) = 1;
EDIT - following error shown in comments below
You can use the STIsValid Method to detect if you have shape that's invalid. The method will return 0 if invalid.
The MakeValid Method will fix invalid shape data
for example:
UPDATE table SET geom = geom.MakeValid() where geom.STIsValid() = 0
Note
As the error suggests, the MakeValid could alter your shape in a way that you might consider incorrect, depending on the original problem with the shape. So you should confirm that you're happy with the "corrected" shape before proceeding.

Related

Cannot input parameters in SQL code for MS query

I'm creating an Excel report, which other users beside myself could manage.
At the moment I'm struggling with creating the parameters in MS Query, so that they would get the input from a cell in Excel.
Everytime I try to paste my code, where I have changed the original dates with the "question marks" I get the following error.
"Parameters are not allowed in queries that can't be displayed grpahically."
I have tried to create parameters for very simple queries. Like
select *
From dmbase.test
where ID = ?
And there the parameters work, I could add even 10 or more and it would still work.
In addition I have tried to paste the code as it is in SSMS and then later through Data-Properties->Query Properties ->Definitions to change the code and add parameters to the "Command Text" box, but Excel just gives an error.
Also tried to declare variables for my parameters, but that didn't work as well. Gave an error regarding symbols.
declare Parameter1 date(10)
set Parameter1 = ?
declare Parameter2 date(10)
set Parameter2 = ?
I'm not 100% sure that the joins are to blame, but that's my feeling.
My code can be seen below.
select
loc.LocationLang
,loc.DistrictLang
,loc.InventoryRegionLang
,cod.ContractNumber
,cus.CustomerLang
,cus.InternalCustomerType
,cus.CustomerGroupCode
,cus.Organizationalcode
,css.CustomerSubSegmentLang
,loc.AnalysisRegionLang
,dht.ContractHeaderTypeLang
,cod.RentalOutDate
from
dmbase.fContractOpenDetail as cod
left join dmbase.dLocation as loc
on cod.LocationID = loc.LocationID
left join dmbase.dCustomer as cus
on cod.CustomerID = cus.CustomerID
left join dmbase.dCustomerSubSegment as css
on cus.CustomerSubsegmentID = css.CustomerSubSegmentID
left join dmbase.dContractHeaderType as dht
on cod.ContractHeaderTypeAMID = dht.ContractHeaderTypeAMID
where
cod.CompanyID = '6'
and cod.RentalOutDate between ? and ?
and left(loc.LocationLang,4) = '7201'
order by cod.ContractNumber
I would appreciate if you could say, how I could put parameters in so that I would not get the error of "Parameters are not allowed...".

Error SQLCODE=-789, SQLSTATE=429BB using the function ST_Contains

I'm getting the error
The data type for parameter or SQL variable "SHAPE" is not supported in the routine, compound SQL statement, or parameter list of a cursor value constructor.. SQLCODE=-789, SQLSTATE=429BB, DRIVER=4.18.60
When I use the code
CREATE OR REPLACE TRIGGER z
BEFORE INSERT OR UPDATE ON x
REFERENCING NEW AS N
FOR EACH ROW
BEGIN
DECLARE contador INTEGER;
SET contador = (SELECT COUNT(*) FROM y s
WHERE NOT(n.yID = s.yID AND db2gse.ST_Contains(s.shape, n.shape) = 1));
IF contador > 0 THEN
SIGNAL SQLSTATE '20001' SET MESSAGE_TEXT ='invalid relationship';
END IF;
END#
But if take out the function ST_Contains, it's works, I don't have a clue why that happens.
EDIT: Windows 7 64bit Ultimate with DB2 11.1 Server edition with ibm data studio, sorry I forgot about this detail.
Well, the error message does give you a clue: structured types (which ST_Geometry and its children are) are not supported in compound SQL statements, such as your trigger body. You'll need to do this check before you convert data from the exchange format to geometry or store the exchange format in the table along with geometry.
In the latter case you would have, along with the shape ST_Geometry column another one, e.g. shape_wkt varchar(5000) and in the trigger do type conversion on the fly:
...AND db2gse.ST_Contains(
db2gse.ST_Geometry(s.shape_wkt),
db2gse.ST_Geometry(n.shape_wkt)
)
db2gse.ST_Geometry(s.shape_wkt) might be optional, because the value does not need to be instantiated in the trigger, so this might work:
...AND db2gse.ST_Contains(
s.shape,
db2gse.ST_Geometry(n.shape_wkt)
)

Postgis query to update linestring

while executing this query i am getting error
UPDATE treedetailsentered
set geom_line=st_geomfromtext('LineString(('||longitude||' '||latitude||','||lon2||' '||lat2||'))', 4326);
error
ERROR: parse error - invalid geometry
HINT: "LineString((7" <-- parse error at position 13 within geometry
********** Error **********
this is how i created column in table for the linestring
ALTER TABLE public.treedetailsentered
ADD COLUMN geom_line geometry(LineString, 4326)
It's hard to tell what the exact problem is without knowing what type longitude, latitude have, but my guess is that you're not forming a proper string.
My advice is to debug this by first creating a proper text via a query that's simpler:
select 'LineString(('||longitude||' '||latitude||','||lon2||' '||lat2||'))'
Depending on what types you have, you might have to do some conversions, like this:
select 'LineString(('||longitude::text||' '||latitude::text||','||lon2::text||' '||lat2::text||'))'
If you already have texts, make sure that the numbers are properly formatted. Floats are expected to have a dot decimal separator for example.
I have added an extra bracket i removed that it worked for me.
UPDATE treedetailsentered set geom_line=ST_GeomFromText('LINESTRING(' || longitude || ' '||latitude||','||lon2||' '||lat2||')', 4326);

PostgreSQL query within PostGIS function

I am trying to run the following PostGIS query:
select ST_distance_spheroid(
ST_GeomFromText('POINT(
(select AsText(location) from test where name="EGMC")
)', 4326),
ST_GeomFromText('POINT(
(select AsText(location) from test where name="EGDY")
)', 4326),
'SPHEROID["WGS_1984",6378137,298.257223563]'
);
but keep getting an error:
ERROR: parse error - invalid geometry
HINT: "POINT(
(s" <-- parse error at position 9 within geometry
I'm happy that I know what the error means, I just don't know how to go about achieving what I want to do. I don't want to manually specify the location, it's stored in the database! I know the name of the place, so I want to get it's location by looking it up. How should I be doing this? Also, it seems a bit unnecessary to convert to a string to convert back, what else can I do?
If I can do this without having to specify variables that would be great.
Thanks.
You are mixing SQL and WKT, which are not the same. Furthermore, you don't need to recreate geometries that already exist. Query the existing geometries instead:
select ST_distance_spheroid(g1.location, g2.location, 'SPHEROID["WGS_1984",6378137,298.257223563]')
from test g1, test g2
where g1.name = "EGMC" and g2.name = "EGDY";

SQL Server 2008 Geometry not working?

I'm having an issue with SQL Server 2008 and the geometry functions. I'm trying to create non-overlapping shapes using the STDifference function... but it does not seem to be working 100% of the time.
Here is all the sample code to demonstrate the issue. Anybody have any idea to make these non-overlapping polygons? (except "don't make your polygons so complex")
-- create our Geometry polygons.
DECLARE #Geo1 Geometry, #Geo2 Geometry;
SET #Geo1 = geometry::STGeomFromText('POLYGON ((-79725887.5234375 42951274.765625, -79699548.921875 42991827.84375, -79695546.375697568 42997990.498925969, -79695559.967852488 42998690.733179785, -79696152.0625 43029192.375, -79715247.75 43051708.75, -79802181.8984375 43020797.71875, -79806253.6640625 43018621.6953125, -79810436.03125 43014767.046875, -79825837.5 43000572.375, -79830640.625 42973672.03125, -79832936.7265625 42960812.4296875, -79725887.5234375 42951274.765625))',0);
SET #Geo2 = geometry::STGeomFromText('POLYGON ((-79863430.6875 42937209.4375, -79850399.0625 42940068.75, -79850394.9375 42940069.625, -79845320.6875 42946082.625, -79843216.25 42948576.375, -79832949.125 42960743, -79814909.939453125 43061773.556640625, -79817218.30078125 43060262.947265625, -79823496.6875 43056154.3125, -79867800.5 43027161.5625, -79871834.50390625 43024521.70703125, -79875660.228515625 43022018.123046875, -79875666.8125 43022013.8125, -79875674.536313191 43022008.760254942, -79875676.408203125 43022007.53515625, -79875677.236328125 43022006.994140625, -79875718.458984375 43021980.017578125, -79875728.506891936 43021973.442301653, -79881723.017578125 43018050.58984375, -79882437.0625 43017583.3125, -79882585.375 43017486.25, -79884466.9375 43016254.9375, -79884550.875 43016200, -79886514.3125 43014915.125, -79887785.5 43014083.25, -79887790.4375 43014080, -79887793.125 43014078.26953125, -79887807.171875 43014069.076171875, -79887825.568359375 43014057.03515625, -79887831.322335 43014053.269705132, -79888029.5 43013923.5625, -79890094.5625 43012572.1875, -79934236.875 42983685.125, -79863430.6875 42937209.4375))',0);
-- A quick test so you can see them
SELECT #Geo1, 'Geo1' as MyName UNION ALL SELECT #Geo2, 'Geo2' as MyName;
-- how do they compare initially?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- try to make them NOT overlap or intersect
SET #Geo1 = #Geo1.STDifference(#Geo2);
SET #Geo2 = #Geo2.STDifference(#Geo1);
-- Now, how do they compare?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- what does the intersection look like?
SELECT #Geo1.STIntersection(#Geo2).STAsText();
This is the final select result:
MULTIPOLYGON (((-79831832.015625 42966999.5078125, -79830502.34765625 42974446.45703125, -79830181.430394545 42976243.79133676, -79830220.96484375 42976022.375, -79831832.015625 42966999.5078125)), ((-79832481.0538819 42963364.484146826, -79832328.75390625 42964217.45703125, -79831832.015625 42966999.5078125, -79832481.0538819 42963364.484146826)))
Not an answer, just an observation... I get different results if I introduce two new variables for the two differences.
-- create our Geometry polygons.
DECLARE #Geo1 Geometry, #Geo2 Geometry, #Geo3 Geometry, #Geo4 Geometry;
SET #Geo1 = geometry::STGeomFromText('POLYGON ((-79725887.5234375 42951274.765625, -79699548.921875 42991827.84375, -79695546.375697568 42997990.498925969, -79695559.967852488 42998690.733179785, -79696152.0625 43029192.375, -79715247.75 43051708.75, -79802181.8984375 43020797.71875, -79806253.6640625 43018621.6953125, -79810436.03125 43014767.046875, -79825837.5 43000572.375, -79830640.625 42973672.03125, -79832936.7265625 42960812.4296875, -79725887.5234375 42951274.765625))',0);
SET #Geo2 = geometry::STGeomFromText('POLYGON ((-79863430.6875 42937209.4375, -79850399.0625 42940068.75, -79850394.9375 42940069.625, -79845320.6875 42946082.625, -79843216.25 42948576.375, -79832949.125 42960743, -79814909.939453125 43061773.556640625, -79817218.30078125 43060262.947265625, -79823496.6875 43056154.3125, -79867800.5 43027161.5625, -79871834.50390625 43024521.70703125, -79875660.228515625 43022018.123046875, -79875666.8125 43022013.8125, -79875674.536313191 43022008.760254942, -79875676.408203125 43022007.53515625, -79875677.236328125 43022006.994140625, -79875718.458984375 43021980.017578125, -79875728.506891936 43021973.442301653, -79881723.017578125 43018050.58984375, -79882437.0625 43017583.3125, -79882585.375 43017486.25, -79884466.9375 43016254.9375, -79884550.875 43016200, -79886514.3125 43014915.125, -79887785.5 43014083.25, -79887790.4375 43014080, -79887793.125 43014078.26953125, -79887807.171875 43014069.076171875, -79887825.568359375 43014057.03515625, -79887831.322335 43014053.269705132, -79888029.5 43013923.5625, -79890094.5625 43012572.1875, -79934236.875 42983685.125, -79863430.6875 42937209.4375))',0);
-- A quick test so you can see them
SELECT #Geo1, 'Geo1' as MyName UNION ALL SELECT #Geo2, 'Geo2' as MyName;
-- how do they compare initially?
SELECT
#Geo1.STTouches(#Geo2) as 'Touches'
,#Geo1.STOverlaps(#Geo2) as 'Overlaps'
,#Geo1.STIntersects(#Geo2) as 'Intersects'
-- try to make them NOT overlap or intersect
SET #Geo3 = #Geo1.STDifference(#Geo2);
SET #Geo4 = #Geo2.STDifference(#Geo1);
-- Now, how do they compare?
SELECT
#Geo3.STTouches(#Geo4) as 'Touches'
,#Geo3.STOverlaps(#Geo4) as 'Overlaps'
,#Geo3.STIntersects(#Geo4) as 'Intersects'
-- what does the intersection look like?
SELECT #Geo3.STIntersection(#Geo4).STAsText();
Compare:
Touches Overlaps Intersects
1 0 1
Final Select:
MULTIPOINT ((-79830220.96484375 42976022.375), (-79831832.015625 42966999.5078125))
I suspect this is due to the method/precision with which SQL Server performs spatial calculations. For operations like STIntersection() etc, SQL Server rounds the supplied float coordinate values to a 27 bit integer grid. This can introduce slight distortions to the coordinates returned as the result of spatial operations.
In your case, your coordinate values are large, which means that the fixed size integer grid must be made quite coarse to accommodate the full range of data. The relative difference between the intersecting coordinates that you're trying to remove, however, is very small. When snapped to this coarse grid, SQL Server is unable to correctly identify the area of intersection.
See here for a explanation, and also a suggestion that this situation has been improved in SQL Server Denali:
https://connect.microsoft.com/SQLServer/feedback/details/580254/spatial-operations-are-done-with-a-low-precision-causing-troubles-in-the-returned-data
As pointed out by Joe Stefanelli, your polygons don't technically overlap but they do intersect. The reason is that if you cut a hole out of one polygon using a smaller polygon, the smaller polygon will not overlap the new polygon but it will intersect it along the edge of the cut. It isn't like a table saw that removes some material along the edge of the cut. I could not include the code because SO is having a problem with certain SQL statements and blocks the post.
SEE REFERENCE A in image
If you would like it not to overlap OR intersect, you can create your own sawblade effect. Apply a very small buffer around the smaller of the geometries when using it in the STDifference() function.
SEE REFERENCE B in image
I know this post is old but it does seem pertinent still for those of us who will still be on 2008 for a while.

Resources