SQL Server Spatial & ArcSDE - Denver Petroleum User Group

Download Report

Transcript SQL Server Spatial & ArcSDE - Denver Petroleum User Group

SQL Server Spatial & ArcSDE
Chris Ebright - Whiting Oil & Gas Corporation
Whiting GIS Environment
• SQL Server 2008 R2
• SQL Server Management Studio 10.50.2500.0
• ArcGIS Server 10.0
• ArcSDE 10.0
• ArcGIS Desktop 10.0
• Python 2.6 (additional modules from standard library)
Why Use SQL Server Spatial Datatypes?
1) Existing Processing on large datasets too slow
•
•
•
Previous processing done with Toolbox and/or Python
Datasets being analized growing, cannot run all processes overnight
SQL Server procedures can be much faster if used correctly
2) 3rd party access to spatial data
•
•
•
Infrastructure of multiple SQL Server Databases
Existing reports could access spatial data within existing procedures
Flexibility for future data access from unknown sources
3) Whiting in-house expertise in SQL Server
•
•
Leverage in-house experience in Query optimization
Backup; Procedures are stored on server and can be understood by multiple
employees. I am only Python programmer, no backup
Challenges of SQL Server Spatial Datatypes
•
Data Management is more complicated
•
No re-projection support with out of the box tools
(SQL Server queries only, ArcGIS will still handle re-projections)
•
Must manage OBJECTIDs if Inserting data
•
May require a new set of skills to interact in SQL Server
environment if no SQL Server experience
Creating Feature Class Using SQL Server Geometry
ArcCatalog– Configuration Keyword
Only one step different than
default feature class creation
Drop down options will vary
Based on which RDBMS is installed
(SQL Server, Oracle, PostGIS, etc.)
GEOMETRY vs. GEOGRAPHY
GEOMETRY
• Cartesian based
• Can store Z and M values, but SQL Spatial functions do not use
• ArcGIS will handle the Z and M values
• Can be cast to GEOGRAPHY for crucial calculations (large features)
• More ST functions
GEOGRAPHY
• Ellipsoidal based
• Can store Z and M values, but SQL Spatial functions do not use
• ArcGIS will NOT handle Z and M values (will error on feature class creation)
Creating Feature Class Using SQL Server SDE Binary
SQL Server MGMT Studio – Business Table Query Results
Creating Feature Class Using SQL Server SDE Binary
SQL Server MGMT Studio – SDE Geometry Lookup
LINESTRING_SDE_BINARY joins
to f1203 to get spatial data
Creating Feature Class Using SQL Server SDE Binary
SQL Server MGMT Studio – SDE Feature Table Query Results
LINESTRING_SDE_BINARY joins
to f1203 to get spatial data
Creating Feature Class Using SQL Server Geometry
SQL Server MGMT Studio – Query Results
LINESTRING_GEOMETRY has
spatial data in business table
Creating Feature Class Using SQL Server Geometry
SQL Server MGMT Studio - Spatial Results Tab
SQL Server MGMT Studio shows
spatial results for SQL Geometries
Editing Feature Class Using SQL Server Geometry
ArcMap - Editing
Notes on Data Management in SQL Server
Lessons Learned Along the Way
• If Adding data to feature class, must manage OBJECTIDs
• Must update feature class extents in sde_layers table
• Layer will plot in ArcMap, but may not display in Map Service
• Must update sde_column_registry table if altering table schema in SQL Server
• Recommend doing schema updates through ArcGIS interface
What has been tested
Tested
• Editing in ArcMap with no additional versions
• Adding/Updating features from SQL Server side
• Creating feature class in ArcGIS first, using configuration keyword
Not Tested
• Editing in ArcMap with multiple versions
• Advanced geodatabase functionality: Topology, Networks, etc.
• Creating table in SQL Server first and registering with SDE command line
SQL Server Spatial Queries
Examples
Example:
Non ArcGIS spatial data access
Scenario:
Users managing wellbore paths in ArcMap.
Other users use spatial attributes in SQL Server.
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
Wellbores – PolylineZM Feature Class stored in SQL Server GEOMETRY
3D View
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE
,SHAPE.STAsText() AS LINESTRING_TEXT
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
OGC Well Known Text
POINT
WKT:
POINT(-100.5 44.1)
GEOMETRY: STGeomFromText(
‘POINT(-100.5 44.1)’, 4267 )
LINESTRING
WKT:
LINESTRING(-100.5 44.1, -100.6 44.05, -100.7 44.0)
GEOMETRY: STGeomFromText(
‘LINESTRING(-100.5 44.1 , -100.6 44.05, -100.7 44.0)’, 4267 )
POLYGON
WKT:
POLYGON((-100.5 44.1, -100.0 44.1, -100.0 43.8, -100.5 43.8, -100.5 44.1))
GEOMETRY: STGeomFromText(
‘POLYGON((-100.5 44.1, -100.0 44.1, -100.0 43.8, -100.5 43.8, -100.5 44.1))’, 4267 )
SQL Server 2008 R2 OGC Methods (GEOMETRY)
STArea
STDisjoint
STIsClosed
STPointOnSurface
STAsBinary
STDistance
STIsEmpty
STRelate
STAsText
STEndpoint
STIsRing
STSrid
STBoundary
STEnvelope
STIsSimple
STStartPoint
STBuffer
STEquals
STIsValid
STSymDifference
STCentroid
STExteriorRing
STLength
STTouches
STContains
STGeometryN
STNumGeometries
STUnion
STConvexHull
STGeometryType
STNumInteriorRing
STWithin
STCrosses
STInteriorRingN
STNumPoints
STX
STDifference
STIntersection
STOverlaps
STY
STDimension
STIntersects
STPointN
SQL Server 2008 R2 Extended Methods
AsGml (geometry Data Type)
MakeValid (geometry Data Type)
AsTextZM (geometry Data Type)
Reduce (geometry Data Type)
BufferWithTolerance (geometry Data Type)
ToString (geometry Data Type)
InstanceOf (geometry Data Type)
Z (geometry Data Type)
Filter (geometry Data Type)
IsNull (geometry Data Type)
M (geometry Data Type)
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE.AsTextZM() AS LINESTRING_TEXT_ZM
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
Z and M Values
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE
,SHAPE.STLength() AS Length
,SHAPE.STNumPoints() AS Num_Points
,SHAPE.STStartPoint() AS SHL
,SHAPE.STEndPoint() AS BHL
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
Native Unit of Geometry (Degrees)
(only 2D length, Z value not used)
Binary Represenation of Geometry
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE
,CAST(geography::STGeomFromText(SHAPE.STAsText(),SHAPE.STSrid).STLength() * 3.28084 AS INT)
AS Length_Feet
,SHAPE.STNumPoints() AS Num_Points
,SHAPE.STStartPoint().STX AS SHL_LON
,SHAPE.STStartPoint().STY AS SHL_LAT
,SHAPE.STEndPoint().STX AS BHL_LON
,SHAPE.STEndPoint().STY AS BHL_LAT
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
Conversion to feet using
Using GEOGRAPHY datatype
Float represenation of coordinates
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT UWI
,SHAPE
,CAST(geography::STGeomFromText(SHAPE.STAsText(),SHAPE.STSrid).STLength() * 3.28084 AS INT) AS
Length_Feet
,SHAPE.STEndPoint().M AS Total_Depth
,CAST(SHAPE.STEndPoint().Z AS INT) AS TVDSS_at_TD
,SHAPE.STNumPoints() AS Num_Points
FROM database.dbo.PATHS
WHERE UWI LIKE '3306100513%'
M value storing MD value
Z value storing TVDSS value
Length Calc without Z input
SQL Server Spatial Queries
Examples – SQL Server MGMT Studio Queries
SELECT t1.[UWI]
,t1.SHAPE.STAsText() AS WellBore_Geometry
,t2.SHAPE.STAsText() AS Basin_Geometry
,t2.Name AS Basin_Name
FROM database.dbo.PATHS AS t1
JOIN
database.dbo.BASINS AS t2
ON
t1.SHAPE.STIntersects(t2.SHAPE) = 1
WHERE UWI LIKE '3306100513%'
Attribute of Intersected Geometry
SQL Server Spatial Queries
Examples – Simple Well Paths
Example:
Simple wellbore path from SHL and BHL
Python vs. SQL Server
SQL Server Spatial Queries
Examples – Simple Well Paths
Python Script
~336,000 wells in 48 min.
import myLogger
import urllib2
import datetime
import time
import arcpy
import sys
import os
import math
#Create Insert cursor on destination table
InsertCursor = arcpy.InsertCursor(fc_well_paths)
ic_row = InsertCursor.newRow()
pointSHL = arcpy.Point()
pointBHL = arcpy.Point()
pointArray = arcpy.Array()
fileAbsolutePath = os.path.abspath(__file__)
try:
for row in SearchCursor:
try:
ic_row.setValue('UWI', row.UWI)
myLog = myLogger.Log(fileAbsolutePath)
myLog.reportStart()
arcpy.env.overwriteOutput = 1
if row.WELL_NAME == None:
#Set workspace
arcpy.env.workspace = r'Database Connections\server.database.sde'
env = arcpy.env.workspace
ic_row.setValue('WELL_NAME', '')
elif row.WELL_NUMBER == None:
fc_well_paths = r'Database Connections\server.database.sde\database.DBO.WELL_PATHS'
if row.WELL_NAME == None:
#Check if feature already exists, and if so, delete
if arcpy.Exists(fc_well_paths):
print "exists"
#arcpy.Delete_management(fc)
arcpy.DeleteFeatures_management(fc_well_paths)
else:
print "doesn't exist"
#Create spatial reference
sr = arcpy.SpatialReference()
sr.factoryCode = 4267
arcpy Cursors and Loops
SLOWER
#Create feature class based on template
arcpy.CreateFeatureclass_management(env, fc_well_paths, 'POLYLINE', '', '', '', sr)
if len(arcpy.Describe(fc_well_paths).fields) > 2:
pass
else:
arcpy.AddField_management(fc_well_paths, 'UWI', 'text')
arcpy.AddField_management(fc_well_paths, 'WELL_NAME', 'text')
ic_row.setValue('WELL_NAME', '')
else:
ic_row.setValue('WELL_NAME', row.WELL_NAME)
else:
ic_row.setValue('WELL_NAME', str(row.WELL_NAME) + ' ' + str(row.WELL_NUMBER))
pointArray.removeAll()
pointSHL.X = row.getValue('SURFACE_LONGITUDE')
pointSHL.Y = row.getValue('SURFACE_LATITUDE')
pointBHL.X = row.getValue('BOTTOM_HOLE_LONGITUDE')
pointBHL.Y = row.getValue('BOTTOM_HOLE_LATITUDE')
pointArray.add(pointSHL)
pointArray.add(pointBHL)
newLine = arcpy.Polyline(pointArray)
ic_row.setValue('SHAPE', newLine)
InsertCursor.insertRow(ic_row)
#Create Search cursor on source table
SearchCursor = arcpy.SearchCursor(r'Database Connections\server.database2sde\database2.dbo.WELLS_SURF', \
'BOTTOM_HOLE_LATITUDE IS NOT NULL AND \
BOTTOM_HOLE_LONGITUDE IS NOT NULL AND \
BOTTOM_HOLE_LONGITUDE <> 0 AND \
BOTTOM_HOLE_LATITUDE <> 0 AND \
SURFACE_LONGITUDE <> 0 AND \
SURFACE_LATITUDE <> 0 AND \
BOTTOM_HOLE_LATITUDE <> SURFACE_LATITUDE AND \
BOTTOM_HOLE_LONGITUDE <> SURFACE_LONGITUDE', '', '', '')
except Exception, e:
myLog.reportError(e)
del InsertCursor, ic_row, pointSHL, pointBHL, pointArray
except Exception, e:
myLog.reportError(e)
myLog.reportToDatabase('FALSE', e)
#sys.exit()
SQL Server Script
~336,000 wells in 2 min.
DELETE FROM database.dbo.PATHS_SIMPLE
INSERT INTO database.dbo.PATHS_SIMPLE (
OBJECTID
,SHAPE
,WELL_NAME
)
(
SELECT
ROW_NUMBER() OVER(ORDER BY COMPLETION_DATE)
,geometry::STGeomFromText(
'LINESTRING(' + STR(SURFACE_LONGITUDE, 25, 25) + ' ' +
STR(SURFACE_LATITUDE, 25, 25) + ',' +
STR(BOTTOM_HOLE_LONGITUDE, 25, 25) + ' ' +
STR(BOTTOM_HOLE_LATITUDE, 25, 25) + ')'
, 4267)
,WELL_NAME + ' ' + WELL_NUM
FROM database2.dbo.WELL
WHERE
BOTTOM_HOLE_LATITUDE IS NOT NULL AND
BOTTOM_HOLE_LONGITUDE IS NOT NULL AND
BOTTOM_HOLE_LONGITUDE <> 0 AND
BOTTOM_HOLE_LATITUDE <> 0 AND
SURFACE_LONGITUDE <> 0 AND
SURFACE_LATITUDE <> 0 AND
BOTTOM_HOLE_LATITUDE <> SURFACE_LATITUDE AND
BOTTOM_HOLE_LONGITUDE <> SURFACE_LONGITUDE
)
Set based SQL Query
FASTER
Python Integration
Code Snippets
import pyodbc
Open Connection to SQL Server table
conn = pyodbc.connect('DRIVER={SQL Server};SERVER=<server>;DATABASE=<database>')
c = conn.cursor()
Execute SELECT statement on table
cursor.execute('SELECT MAX(OBJECTID) FROM featureClass')
oid = cursor.fetchall()[0][0]
Execute SELECT statement on table
cursor.execute('SELECT COUNT(*) FROM featureClass WHERE ID = ?', var_id)
count = cursor.fetchall()[0][0]
Execute INSERT statement on table
sql = "INSERT INTO featureClass(OBJECTID, SHAPE) (SELECT %d, %s)" % (oid, geometry)
cursor.execute(sql)
conn.commit()
Execute UPDATE statement on table
cursor.execute("UPDATE featureClass SET ID = oid + '_' + subID")
conn.commit()
SQL Server Spatial Queries
Examples – Spatial Analysis for Wellbores in Fields
SQL Server Spatial Queries
Examples – View From Spatial Query
SELECT t1.UWI
,t1.SHAPE.STStartPoint().STY AS SHL_LAT
,t1.SHAPE.STStartPoint().STX AS SHL_LON
,t1.SHAPE.STEndPoint().STY AS BHL_LAT
,t1.SHAPE.STEndPoint().STX AS BHL_LON
,t1.SHAPE.STEndPoint().M AS TD
,t1.SHAPE.STEndPoint().Z AS TVDSS_TD
,t2.name AS Basin
,t3.name AS Field
FROM database.dbo.PATHS AS t1
JOIN
database.dbo.BASINS AS t2
ON
t1.SHAPE.STIntersects(t2.SHAPE) = 1
JOIN
database.dbo.FIELDS AS t3
ON
t1.SHAPE.STIntersects(t3.SHAPE) = 1
WHERE t1.UWI LIKE '%33061%'
Dynamic Intersect of wellbores
and field outlines
SQL Server Spatial Queries
Examples – Excel Linking to SQL Server view
UWI
33061012810000
33061012830000
33061012840000
33061012850000
33061012860000
33061012890000
33061012890000
33061012890100
33061012890100
33061012910000
33061012910000
33061012910100
33061012910100
33061012930000
33061012940100
33061012950000
33061012950100
33061012950200
33061012950300
33061012960000
33061012970000
33061012980000
33061012990000
33061013000000
33061013010000
33061013030000
33061013030000
33061013030100
SHL_LAT
SHL_LON
BHL_LAT
BHL_LON
TD
47.8469638
-102.4013162
47.82176924
-102.4007689
48.17510063
-102.5050341
48.18074926
-102.5465628
48.07808842
-102.5236354
48.05379697
-102.519398
48.29890103
-102.5051834
48.3111511
-102.5189636
48.09465782
-102.2814816
48.08296043
-102.2693611
48.40238924
-102.8263396
48.42956384
-102.8312775
48.40238924
-102.8263396
48.42956384
-102.8312775
48.40238924
-102.8263396
48.42956835
-102.8312966
48.40238924
-102.8263396
48.42956835
-102.8312966
48.40239041
-102.8267512
48.42956577
-102.8381938
48.40239041
-102.8267512
48.42956577
-102.8381938
48.40239041
-102.8267512
48.42954232
-102.838462
48.40239041
-102.8267512
48.42954232
-102.838462
48.28440775
-102.559069
48.25537918
-102.5579144
47.93351284
-102.4788547
47.92141017
-102.4747555
47.81787922
-102.4656598
47.81633447
-102.4656387
47.81787922
-102.4656598
47.80098009
-102.4639435
47.81787922
-102.4656598
47.80216198
-102.4640192
47.81787922
-102.4656598
47.79109206
-102.4631314
47.89002705
-102.2352256
47.87799745
-102.226253
48.10859343
-102.436319
48.10544051
-102.3973608
48.03827066
-102.2980918
48.05028143
-102.3075429
48.0391278
-102.2895798
48.06365464
-102.3074976
48.32780537
-102.483963
48.34013288
-102.4975229
47.94764525
-102.2759062
47.9619009
-102.2944982
47.85867453
-102.2737543
47.85765902
-102.3034023
47.85867453
-102.2737543
47.85765902
-102.3034023
47.85867453
-102.2737543
47.85785747
-102.3112671
17213
18015
9316
12899
12505
19185
19185
19158
19158
20124
20124
20118
20118
17992
12784
8740
14365
13933
17993
12302
17311
12435
17363
12746
13257
16063
16063
18009
TVDSS_TD
Basin
-6424.591983 WILLISTON BASIN
-5695.602066 WILLISTON BASIN
1731.908387 WILLISTON BASIN
-5291.967185 WILLISTON BASIN
-5203.131073 WILLISTON BASIN
-7413.212465 WILLISTON BASIN
-7413.212465 WILLISTON BASIN
-7307.849413 WILLISTON BASIN
-7307.849413 WILLISTON BASIN
-7387.343073 WILLISTON BASIN
-7387.343073 WILLISTON BASIN
-7289.199102 WILLISTON BASIN
-7289.199102 WILLISTON BASIN
-5637.707683 WILLISTON BASIN
-6638.841291 WILLISTON BASIN
-6514.837079 WILLISTON BASIN
-6442.769883 WILLISTON BASIN
-6444.988622 WILLISTON BASIN
-6410.967479 WILLISTON BASIN
-5674.628805 WILLISTON BASIN
-5778.43068 WILLISTON BASIN
-5338.195557 WILLISTON BASIN
-5497.51321 WILLISTON BASIN
-5228.140241 WILLISTON BASIN
-5369.170037 WILLISTON BASIN
-7854.478002 WILLISTON BASIN
-7854.478002 WILLISTON BASIN
-7905.065345 WILLISTON BASIN
Dynamic link to SQL Server View
Updates on feature class update
Field
VAN HOOK
SANISH
SANISH
ALGER
PARSHALL
WHITE EARTH
PLEASANT VALLEY
WHITE EARTH
PLEASANT VALLEY
WHITE EARTH
PLEASANT VALLEY
WHITE EARTH
PLEASANT VALLEY
ALGER
BIG BEND
VAN HOOK
VAN HOOK
VAN HOOK
VAN HOOK
PARSHALL
SANISH
PARSHALL
PARSHALL
ALGER
PARSHALL
PARSHALL
VAN HOOK
PARSHALL
SQL Server Spatial Queries
Examples – View From Spatial Query
SELECT t2.name AS Field
,COUNT(t1.SHAPE) AS Total_Wellbores
,MAX(CAST(geography::STGeomFromText(t1.SHAPE.STAsText(),t1.SHAPE.STSrid).STLength() * 3.28084 AS INT) ) AS
Longest_Wellbore
,AVG(CAST(geography::STGeomFromText(t1.SHAPE.STAsText(),t1.SHAPE.STSrid).STLength() * 3.28084 AS INT) ) AS Avg_Wellbore
,SUM(t1.SHAPE.STEndPoint().M) AS Total_Feet_Drilled
FROM database.dbo.PATHS AS t1
JOIN
database.dbo. FIELDS AS t2
ON
t1.SHAPE.STIntersects(t2.SHAPE) = 1
WHERE t1.UWI LIKE '%33061%'
GROUP BY t2.name
ORDER BY Avg_Wellbore DESC
SQL Server Spatial Queries
Examples – Excel Linking to SQL Server view
Field
Total_Wellbores
Longest_Wellbore
Avg_Wellbore
Total_Feet_Drilled
PLEASANT VALLEY
15
11221
9713
80508
SORKNESS
10
10591
9709
154366
BIG BUTTE
64
11744
9695
746954
ALKALI CREEK
52
12260
9514
782042
REUNION BAY
70
13653
9419
1125619
WHITE EARTH
11
11221
9378
115260
MANITOU
55
11694
9029
819613
ROBINSON LAKE
70
11906
8857
914325
ROSS
101
12319
8747
1047145
ALGER
210
13182
8657
2772412
KITTLESON SLOUGH
38
10747
8511
428223
SANISH
534
12777
8408
6280677
BASKIN
7
11732
7946
111073
COTTONWOOD
45
10590
7634
392902
EAST TIOGA
16
10734
7505
191527
CLEAR WATER
80
11237
7356
811861
125
15003
7319
1405354
8
10905
7137
111020
94
12319
7122
855890
2
11383
6636
30124
BIG BEND
54
11076
6404
704987
PARSHALL
319
13442
6351
3063418
2
10338
6058
30574
TIOGA
27
11081
2840
185300
PLAZA
1
2280
2280
8479
WABEK
4
1939
1649
21383
COULEE
1
78
78
VAN HOOK
ENGET LAKE
STANLEY
WHITE LAKE
POWERS LAKE
Dynamic link to SQL Server View
Updates on feature class update
Find Psuedo Midpoint of Linestring
Update Procedure
;WITH PATHS_CTE(rownumber
,UWI
,ROW_CHANGED_DATE
,midpoint
)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY UWI)
,[UWI]
,ROW_CHANGED_DATE
,SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001).STIntersection(SHAPE).STStartPoint() AS
midpoint
FROM database.dbo.PATHS
WHERE ROW_CHANGED_DATE > @maxDate
)
MERGE INTO database.dbo.PATHS_MIDPOINT AS t1
USING PATHS_CTE AS t2
ON t2.UWI = t1.UWI
WHEN MATCHED
THEN UPDATE
SET
UWI = t2.UWI
,t1.ROW_CHANGED_DATE = GETDATE()
,t1.SHAPE = t2.midpoint
WHEN NOT MATCHED
THEN INSERT (
[OBJECTID]
,[UWI]
,ROW_CHANGED_DATE
,[SHAPE]
)
VALUES (
rownumber + @oid
,[UWI]
,GETDATE()
,midpoint
)
;
Using MERGE statement allows efficient
updating and inserting of data into
feature classes in one process by filtering
on ROW_CHANGED_DATE
SQL Server Spatial Queries
Examples
Example:
True Midpoint on Line (User defined function)
vs.
Pseudo Midpoint on Line (pure ST Functions)
(useful for plotting wellbore specific attributes)
WORK IN PROGRESS
SQL Server Spatial Queries
Symbolizing
Production Plotted at Surface Hole Location
Production Plotted at Wellbore Midpoint
SQL Server Non-Spatial Queries
SQL Server MGMT Studio – Midpoint on Linestring
USE database
IF OBJECT_ID('tempdb..#NDIC_HORZ_LIST') IS NOT NULL
DROP TABLE #NDIC_HORZ_LIST
SET NOCOUNT OFF
-- Create temp table to hold the OBJECTID and apply filter on wells without enough points
SELECT lineID = identity (int,1,1), OBJECTID INTO #NDIC_HORZ_LIST FROM database.dbo.API12_PATHS
CREATE CLUSTERED INDEX idx_NDIC_HORZ_LIST_lineid ON #NDIC_HORZ_LIST(lineID)
CREATE INDEX idx_NDIC_HORZ_LIST_objectid ON #NDIC_HORZ_LIST(OBJECTID)
DECLARE @midPoint geometry
DECLARE @point1X numeric(25,20)
DECLARE @point1Y numeric(25,20)
DECLARE @point2X numeric(25,20)
DECLARE @point2Y numeric(25,20)
DECLARE @xDiff numeric(25,20)
DECLARE @yDiff numeric(25,20)
DECLARE @workingLineLength1 numeric(25,20) = 0
DECLARE @workingLineLength2 numeric(25,20) = 0
DECLARE @lineLength numeric(25,20)
DECLARE @i int
DECLARE @lineID int
DECLARE @lineOID INT
Multiple While Loop Operations
(analogous to Python function)
SLOWER
DECLARE @line geometry
DECLARE @workLine geometry
DECLARE @lastSegment geometry
DECLARE @lineFromString NVARCHAR(MAX)
SET @lineID = 1
-- Outer loop to iterate over lines in table, using the counts from the temp table
WHILE @lineID <= (SELECT COUNT(*) FROM #NDIC_HORZ_LIST)
BEGIN
-- Assign OBJECTID FROM Temp table to variable
SET @lineOID = (SELECT OBJECTID FROM #NDIC_HORZ_LIST WHERE lineID = @lineID)
-- Assign SHAPE From table to geometry variable
SET @line = (SELECT SHAPE FROM database.dbo.API12_PATHS WHERE OBJECTID = @lineOID)
SET @lineLength = @line.STLength() / 2
SET @lineFromString = 'LINESTRING('
SET @i = 1
Loop 1
Loop 2
-- Loop through points in line until the working length is longer than half the line length
WHILE @workingLineLength2 < @lineLength
BEGIN
-- For first point add start point from line
IF @i = 1
BEGIN
SET @lineFromString = @lineFromString + CAST(@line.STStartPoint().STX AS VARCHAR(10)) + ' ' + CAST(@line.STStartPoint().STY AS VARCHAR(10)) + ')'
END
ELSE
BEGIN
-- Strip the trailing ) from the line string text
SET @lineFromString = LEFT(@lineFromString, LEN(@lineFromString) - 1)
SET @lineFromString = @lineFromString + ',' + CAST(@line.STPointN(@i).STX AS VARCHAR(10)) + ' ' + CAST(@line.STPointN(@i).STY AS VARCHAR(10)) + ')'
SET @workLine = geometry::STGeomFromText(@lineFromString, 4267)
SET @lastSegment = geometry::STGeomFromText('LINESTRING(' +
CAST(@line.STPointN(@i - 1).STX AS VARCHAR(10)) + ' ' + CAST(@line.STPointN(@i - 1).STY AS VARCHAR(10)) + ',' +
CAST(@line.STPointN(@i).STX AS VARCHAR(10)) + ' ' + CAST(@line.STPointN(@i).STY AS VARCHAR(10)) + ')', 4267)
SET @workingLineLength2 = @workLine.STLength()
IF @workingLineLength2 > @lineLength
BEGIN
SET @point1X = @line.STPointN(@i - 1).STX
SET @point1Y = @line.STPointN(@i - 1).STY
SET @point2X = @line.STPointN(@i).STX
SET @point2Y = @line.STPointN(@i).STY
SET @xDiff = (@point2X - @point1X) * ((@lineLength - @workingLineLength1) / @lastSegment.STLength())
SET @yDiff = (@point2Y - @point1Y) * ((@lineLength - @workingLineLength1) / @lastSegment.STLength())
SET @midPoint = geometry::STGeomFromText('POINT(' + CAST(@point1X + @xDiff AS VARCHAR(25)) + ' ' + CAST(@point1Y + @yDiff AS VARCHAR(25)) + ')',4267)
INSERT INTO database.dbo.API10_SHL(OBJECTID,SHAPE)
SELECT
ROW_NUMBER() OVER(ORDER BY t2.OBJECTID), @midPoint FROM database.dbo.API12_PATHS AS t2
END
SET @workingLineLength1 = @workingLineLength2
END
SET @i = @i + 1
END
SET @lineID = @lineID + 1
END
SQL Server Non-Spatial Queries
SQL Server MGMT Studio – Midpoint on Linestring
Add each line segment until half line length
+
+
+
+
+
+
SQL Server Spatial Queries
SQL Server MGMT Studio – Psuedo Midpoint on Linestring
Set Based Operation
FASTER
SELECT
SHAPE.STEnvelope().
STCentroid().
STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001).
STIntersection(SHAPE).
STStartPoint()
FROM WELL_PATHS
Find Psuedo Midpoint of Linestring
SELECT
SHAPE.STEnvelope()
Find Psuedo Midpoint of Linestring
SELECT
SHAPE.STEnvelope().
STCentroid()
Find Psuedo Midpoint of Linestring
SELECT
SHAPE.STEnvelope().
STCentroid().
STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001)
Find Psuedo Midpoint of Linestring
SELECT
SHAPE.STEnvelope().
STCentroid().
STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001).
STIntersection(SHAPE)
Find Psuedo Midpoint of Linestring
SELECT
SHAPE.STEnvelope().
STCentroid().
STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001).
STIntersection(SHAPE).
STStartPoint()
Find Psuedo Midpoint of Linestring
Statistical Analysis
STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) + .000001)
Hard Coded Number
-analyze validity
End Point
Start Point
Distance of Intersection
Intersection
Buffer Polygon
Well Path
Find Psuedo Midpoint of Linestring
Statistical Analysis
;WITH CTE_PATHS_STATS(dist) AS
( SELECT geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000001).STIntersection(SHAPE).STStartPoint().STAsBinary(),4267)
.STDistance(
geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000001).STIntersection(SHAPE).STEndPoint().STAsBinary(), 4267) )
FROM database.dbo.PATHS
)
SELECT MAX(dist) AS max_dist_meter
,MIN(dist) AS min_dist_meter
,AVG(dist) AS avg_dist_meter
,COUNT(dist) AS count_dist
,(SELECT COUNT(*) FROM PATHS_STATS) AS count_total
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 1) AS GreaterThan1m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 5) AS GreaterThan5m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 10) AS GreaterThan10m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 25) AS GreaterThan25m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 50) AS GreaterThan50m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 100) AS GreaterThan100m
FROM CTE_PATHS_STATS
Find Psuedo Midpoint of Linestring
Statistical Analysis
;WITH CTE_PATHS_STATS(dist) AS
( SELECT geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000005).STIntersection(SHAPE).STStartPoint().STAsBinary(),4267)
.STDistance(
geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000005).STIntersection(SHAPE).STEndPoint().STAsBinary(), 4267) )
FROM database.dbo.PATHS
)
SELECT MAX(dist) AS max_dist_meter
,MIN(dist) AS min_dist_meter
,AVG(dist) AS avg_dist_meter
,COUNT(dist) AS count_dist
,(SELECT COUNT(*) FROM PATHS_STATS) AS count_total
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 1) AS GreaterThan1m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 5) AS GreaterThan5m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 10) AS GreaterThan10m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 25) AS GreaterThan25m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 50) AS GreaterThan50m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 100) AS GreaterThan100m
FROM CTE_PATHS_STATS
Find Psuedo Midpoint of Linestring
Statistical Analysis
;WITH CTE_PATHS_STATS(dist) AS
( SELECT geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000004).STIntersection(SHAPE).STStartPoint().STAsBinary(),4267)
.STDistance(
geography::STGeomFromWKB(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000004).STIntersection(SHAPE).STEndPoint().STAsBinary(), 4267) )
FROM database.dbo.PATHS
)
SELECT MAX(dist) AS max_dist_meter
,MIN(dist) AS min_dist_meter
,AVG(dist) AS avg_dist_meter
,COUNT(dist) AS count_dist
,(SELECT COUNT(*) FROM PATHS_STATS) AS count_total
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 1) AS GreaterThan1m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 5) AS GreaterThan5m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 10) AS GreaterThan10m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 25) AS GreaterThan25m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 50) AS GreaterThan50m
,(SELECT COUNT(dist) FROM PATHS_STATS WHERE dist > 100) AS GreaterThan100m
FROM CTE_PATHS_STATS
Find Psuedo Midpoint of Linestring
Process Refinements
1st Pass Midpoint
Wellbore with one of the highest
Intersection linestring distances
Intersection
linestring
SQL Server Spatial Queries
Psuedo Midpoint on Linestring
Revised Midpoint Prodedure
Intersection Linestring
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE) +
.000004).STIntersection(SHAPE).
STPointN(
Index of Middle Point in Linestring
CAST(
SHAPE.STEnvelope().STCentroid().STBuffer(SHAPE.STEnvelope().STCentroid().STDistance(SHAPE)+.000004).STIntersection(SHAPE).STNumPoints() / 2
AS INT)
)
FROM PATHS
Return the at index of Middle Point
Find Psuedo Midpoint of Linestring
Process Refinements
1st Pass Midpoint
2st Pass Midpoint
THE END