Spatial SQL

1,571 views

Published on

Published in: Business, Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,571
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
108
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • Spatial SQL

    1. 1. An Introduction to spatial queries in SQL Server 2008 VBUG Manchester 24 th July 2008
    2. 2. <ul><li>New data types geometry and geography </li></ul><ul><li>Spatial references </li></ul><ul><li>Spatial operations </li></ul><ul><li>Spatial indexes </li></ul><ul><li>Case study </li></ul>
    3. 3. <ul><li>80-90% of all data has a spatial element </li></ul><ul><ul><li>Where are your customers? </li></ul></ul><ul><ul><li>Where are your assets? </li></ul></ul><ul><ul><li>Where are potential customers? </li></ul></ul><ul><ul><li>Where are the flood risks? </li></ul></ul><ul><ul><li>Where are your complaints coming from? </li></ul></ul><ul><ul><li>Where are the accident black-spots? </li></ul></ul><ul><ul><li>Where are crimes happening? </li></ul></ul>
    4. 4. <ul><li>Postcodes in Glasgow </li></ul><ul><li>Zoned </li></ul><ul><li>Historical reasons </li></ul><ul><li>G5 adjacent to G42 </li></ul><ul><li>G40 in an island </li></ul><ul><li>Postcodes designed for delivering letters </li></ul>
    5. 5. <ul><li>The data analysis engine </li></ul><ul><li>No rendering engine </li></ul><ul><ul><li>Virtual Earth </li></ul></ul><ul><ul><li>Map Point </li></ul></ul><ul><ul><li>Other GIS systems </li></ul></ul><ul><li>OGC Standards compliance </li></ul><ul><ul><li>Plus some “extension” methods of their own </li></ul></ul>
    6. 6. <ul><li>Currently at Release Candidate 0 </li></ul><ul><ul><li>Some features won’t be introduced until RTM </li></ul></ul><ul><li>Feature Pack (RC0) also now available </li></ul><ul><ul><li>Contains CLR Types </li></ul></ul><ul><li>Editions </li></ul><ul><ul><li>Spatial querying available from Express edition up </li></ul></ul>
    7. 7. <ul><li>Basic rendering engine for query results </li></ul><ul><ul><li>SQL Server Management Studio </li></ul></ul>
    8. 8. <ul><li>X/Y coordinate on a planar grid </li></ul><ul><li>British National Grid </li></ul><ul><li>Works well to ~750,000km 2 </li></ul><ul><li>Different projections </li></ul>
    9. 9. <ul><li>Historically easier to use </li></ul><ul><li>Distorts shape, size or position </li></ul><ul><ul><li>Greenland Vs. USA </li></ul></ul><ul><li>More distortion towards the edges </li></ul><ul><li>Planar model based on the Mercator projection </li></ul><ul><li>Lat/Long lines every 10 o </li></ul>
    10. 10. <ul><li>Geodetic coordinates </li></ul><ul><li>Covers larger areas </li></ul><ul><li>International datasets </li></ul><ul><li>Approximation </li></ul><ul><ul><li>Earth actually flattened sphere (oblate spheroid) </li></ul></ul><ul><li>Different models </li></ul><ul><ul><li>Airy 1830 (used by OS) </li></ul></ul><ul><ul><li>WGS84 (used by GPS) </li></ul></ul>
    11. 11. <ul><li>Spatial Reference Identifier </li></ul><ul><li>All spatial data has an SRID </li></ul><ul><li>SRIDs must match for spatial operations </li></ul><ul><ul><li>Null returned if SRIDs don’t match </li></ul></ul><ul><li>Geometry can have an SRID of 0 </li></ul>
    12. 12. SRID Authority WKT Units Factor 4157 EPSG GEOGCS[&quot;Mount Dillon&quot;, DATUM[&quot;Mount Dillon&quot;, ELLIPSOID[&quot;Clarke 1858&quot;, 6378293.64520876, 294.260676369261]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] Clarke's foot 0.304797265 4243 EPSG GEOGCS[&quot;Kalianpur 1880&quot;, DATUM[&quot;Kalianpur 1880&quot;, ELLIPSOID[&quot;Everest (1830 Definition)&quot;, 6377299.36559538, 300.8017]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] Indian foot 0.304799518 4268 EPSG GEOGCS[&quot;NAD27 Michigan&quot;, DATUM[&quot;NAD Michigan&quot;, ELLIPSOID[&quot;Clarke 1866 Michigan&quot;, 6378450.0475489, 294.978697164674]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] US survey foot 0.30480061 4277 EPSG GEOGCS[&quot;OSGB 1936&quot;, DATUM[&quot;OSGB 1936&quot;, ELLIPSOID[&quot;Airy 1830&quot;, 6377563.396, 299.3249646]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] metre 1 4293 EPSG GEOGCS[&quot;Schwarzeck&quot;, DATUM[&quot;Schwarzeck&quot;, ELLIPSOID[&quot;Bessel Namibia (GLM)&quot;, 6377483.86528042, 299.1528128]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] German legal metre 1.000013597 4326 EPSG GEOGCS[&quot;WGS 84&quot;, DATUM[&quot;World Geodetic System 1984&quot;, ELLIPSOID[&quot;WGS 84&quot;, 6378137, 298.257223563]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] metre 1 4748 EPSG GEOGCS[&quot;Vanua Levu 1915&quot;, DATUM[&quot;Vanua Levu 1915&quot;, ELLIPSOID[&quot;Clarke 1880 (international foot)&quot;, 6378306.3696, 293.46630765563]], PRIMEM[&quot;Greenwich&quot;, 0], UNIT[&quot;Degree&quot;, 0.0174532925199433]] foot 0.3048
    13. 13. <ul><li>Point </li></ul><ul><li>LineString </li></ul><ul><li>Polygon </li></ul><ul><li>GeomCollection </li></ul><ul><li>MultiPolygon </li></ul><ul><li>MultiLineString </li></ul><ul><li>MultiPoint </li></ul>From BOL
    14. 14. <ul><li>Two spatial types </li></ul><ul><ul><li>Geometry </li></ul></ul><ul><ul><li>Geography </li></ul></ul><ul><li>CREATE TABLE Venue </li></ul><ul><li>( </li></ul><ul><li>Id INT IDENTITY(1,1) NOT NULL, </li></ul><ul><li>Name NVARCHAR(256), </li></ul><ul><li>Location GEOGRAPHY </li></ul><ul><li>) </li></ul>
    15. 15. <ul><li>A single coordinate </li></ul><ul><li>0 dimensions </li></ul>
    16. 16. <ul><li>INSERT INTO Venue </li></ul><ul><li>VALUES( </li></ul><ul><li>'HBOS', </li></ul><ul><li>geography::STGeomFromText( </li></ul><ul><li>'POINT(-3.29431266523898 ◊ 55.9271035250276)',4326)); </li></ul>
    17. 17. <ul><li>INSERT INTO Venue </li></ul><ul><li>VALUES( </li></ul><ul><li>'Glasgow Caledonian University', </li></ul><ul><li>geography::Parse( </li></ul><ul><li>'POINT(-4.25072511658072 ◊ 55.8659449685365)')); </li></ul>
    18. 18. <ul><li>INSERT INTO Venue </li></ul><ul><li>VALUES( </li></ul><ul><li>‘ Dundee University', </li></ul><ul><li>geography::STGeomFromWKB( </li></ul><ul><li>0x01010000000700ECFAD03A4C4001008000 ◊ B5DF07C0, </li></ul><ul><li>4326)); </li></ul>
    19. 19. <ul><li>INSERT INTO Venue </li></ul><ul><li>VALUES( </li></ul><ul><li>'Microsoft Campus, TVP', </li></ul><ul><li>geography::Point(-0.926690306514502, 51.4618933852762, 4326)); </li></ul>
    20. 20. <ul><li>INSERT INTO Venue </li></ul><ul><li>VALUES( </li></ul><ul><li>Microsoft Edinburgh Office', </li></ul><ul><li>geography::STPointFromText( </li></ul><ul><li>'POINT(-3.2051030639559 ◊ </li></ul><ul><li>55.9523783996701)', 4326)); </li></ul><ul><li>STPointFromWKB also available </li></ul>
    21. 21. <ul><li>SELECT Id, Name, Location.ToString() As LocationText FROM Venue </li></ul>
    22. 22. <ul><li>Very similar – Same methods available </li></ul>
    23. 23. <ul><li>SELECT a.Name AS StartVenue, b.Name AS EndVenue, </li></ul><ul><li>a.Location.STDistance(b.Location) / 1000.0 As Distance </li></ul><ul><li>FROM Venue AS a </li></ul><ul><li>CROSS JOIN Venue AS b </li></ul><ul><li>WHERE a.Id < b.Id </li></ul><ul><li>ORDER BY a.Id, b.Id </li></ul>GCU 60 Dundee U 62 102 MS TVP 520 537 572 MS Edin’ 6 66 58 521 HBOS GCU Dundee U MS TVP
    24. 24. <ul><li>A linestring is a series of coordinates </li></ul><ul><li>1 dimension </li></ul><ul><li>Defines a linear object </li></ul><ul><ul><li>Road </li></ul></ul><ul><ul><li>Railway line </li></ul></ul><ul><ul><li>River </li></ul></ul>
    25. 25. <ul><li>Can use </li></ul><ul><ul><li>STGeomFromText </li></ul></ul><ul><ul><li>STGeomFromWKB </li></ul></ul><ul><ul><li>STLineFromText </li></ul></ul><ul><ul><li>STLineFromWKB </li></ul></ul><ul><ul><li>Parse </li></ul></ul>
    26. 26. <ul><li>geography::STGeomFromText('LINESTRING (2.54223106428981 49.0170682501048, 4.7684115730226 52.3141136672348, -3.36429820396006 55.9505973290652, -0.444141207262874 51.4748916216195, -3.56782372109592 40.4884308949113)', 4326); </li></ul><ul><li>Charles de Gaulle  Schiphol  Turnhouse  Heathrow  Barajas </li></ul>
    27. 27. <ul><li>DECLARE @g geography </li></ul><ul><li>SELECT @g = geography::Parse('LINESTRING (2.54223106428981 49.0170682501048, 4.7684115730226 52.3141136672348, -3.36429820396006 55.9505973290652, -0.444141207262874 51.4748916216195, -3.56782372109592 40.4884308949113)'); </li></ul><ul><li>SELECT @g.STLength() </li></ul><ul><li>---------------------- </li></ul><ul><li>2845161.34954758 </li></ul><ul><li>Result in SI Units (Metres) </li></ul>
    28. 28. <ul><li>Geography uses SI Units </li></ul><ul><li>Geometry uses the units of the planar system </li></ul>The square of the hypotenuse is equal to the sum of the square of the other two sides Not to scale 3 units 4 units ? units Distance from A to B: √ (3 2 +4 2 ) = 5 A B
    29. 29. <ul><li>STIntersection </li></ul><ul><ul><li>The points at which two objects intersect </li></ul></ul><ul><ul><li>Returns a geometry / geography </li></ul></ul><ul><li>STIntersects </li></ul><ul><ul><li>Whether a two objects intersect </li></ul></ul><ul><ul><li>Returns 1 or 0 </li></ul></ul>
    30. 30. <ul><li>DECLARE @a geometry, @b geometry, @c geometry </li></ul><ul><li>SELECT </li></ul><ul><li>@a = geometry::Parse('LINESTRING(0 0, 10 10)'), </li></ul><ul><li>@b = geometry::Parse('LINESTRING(10 0, 0 10)'), </li></ul><ul><li>@c = geometry::Parse('LINESTRING(20 20, 30 30)'); </li></ul><ul><li>SELECT @a.STIntersection(@b).ToString() AS [first], </li></ul><ul><li>@a.STIntersection(@c).ToString() AS [second], </li></ul><ul><li>@a.STIntersects(@c) AS [third] </li></ul><ul><li>first second third </li></ul><ul><li>----------------------------------------------------- </li></ul><ul><li>POINT (5 5) GEOMETRYCOLLECTION EMPTY 0 </li></ul>
    31. 31. <ul><li>A series of coordinates in a closed ring </li></ul><ul><ul><li>First and last coordinate are the same </li></ul></ul><ul><li>2 dimensions </li></ul><ul><li>Defines an area </li></ul>
    32. 32. <ul><li>Interior is everything inside an anti-clockwise ring </li></ul><ul><ul><li>Everything on the left-hand side of the perimeter line. </li></ul></ul>
    33. 33. <ul><li>The specified input does not represent a valid geography instance because it exceeds a single hemisphere. Each geography instance must fit inside a single hemisphere. A common reason for this error is that a polygon has the wrong ring orientation. </li></ul>
    34. 34. <ul><li>Can use </li></ul><ul><ul><li>STGeomFromText </li></ul></ul><ul><ul><li>STGeomFromWKB </li></ul></ul><ul><ul><li>STPolygonFromText </li></ul></ul><ul><ul><li>STPolygonFromWKB </li></ul></ul><ul><ul><li>Parse </li></ul></ul>
    35. 35. <ul><li>geography::STGeomFromText( </li></ul><ul><li>'POLYGON (( -4.23691584728658 55.8676369395107, -4.25517079420388 55.8703819289804, -4.27013483829796 55.8681968506426, -4.26963351666927 55.8562753535807, -4.25607042387128 55.8552713692188, -4.24729574471712 55.8528072573245, -4.23971313983202 55.8606443367898, -4.23691584728658 55.8676369395107))', 4326); </li></ul>
    36. 36. <ul><li>DECLARE @g geography; </li></ul><ul><li>SELECT @g = geography::STGeomFromText('POLYGON ((-4.23691584728658 55.8676369395107, -4.25517079420388 55.8703819289804, -4.27013483829796 55.8681968506426, -4.26963351666927 55.8562753535807, -4.25607042387128 55.8552713692188, -4.24729574471712 55.8528072573245, -4.23971313983202 55.8606443367898, -4.23691584728658 55.8676369395107))', 4326); </li></ul><ul><li>SELECT @g.STLength()/1000.0 AS [Length (km)], @g.STArea()/1000000.0 AS [Area (km^2)] </li></ul><ul><li>Length (km) Area (km^2) </li></ul><ul><li>---------------------- ---------------------- </li></ul><ul><li>6.74090984542709 2.96444752890813 </li></ul>
    37. 37. <ul><li>DECLARE @g geography; </li></ul><ul><li>SELECT @g = geography::STGeomFromText('POLYGON ((-4.23691584728658 55.8676369395107, -4.25517079420388 55.8703819289804, -4.27013483829796 55.8681968506426, -4.26963351666927 55.8562753535807, -4.25607042387128 55.8552713692188, -4.24729574471712 55.8528072573245, -4.23971313983202 55.8606443367898, -4.23691584728658 55.8676369395107))', 4326); </li></ul><ul><li>SELECT Name FROM Venue </li></ul><ul><li>WHERE Location.STIntersects(@g) = 1 </li></ul><ul><li>Name </li></ul><ul><li>------------------------------ </li></ul><ul><li>Glasgow Caledonian University </li></ul>
    38. 38. <ul><li>Coming up in part 2 </li></ul><ul><ul><li>Spatial Indexes </li></ul></ul><ul><ul><li>Estate Agent case study </li></ul></ul>
    39. 39. <ul><li>Estate Agent </li></ul><ul><ul><li>Filter by price, # bedrooms, type – EASY! </li></ul></ul><ul><ul><li>Filter by location? </li></ul></ul><ul><ul><ul><li>Until now very vague </li></ul></ul></ul>
    40. 40. <ul><li>I want a home that is… </li></ul><ul><ul><li>Near a railway station </li></ul></ul><ul><ul><li>In the catchment for a good school </li></ul></ul><ul><ul><li>Near my work </li></ul></ul><ul><ul><li>Near a motorway junction </li></ul></ul><ul><ul><li>Outside the city </li></ul></ul><ul><ul><li>In the city </li></ul></ul>
    41. 41. <ul><li>Railway data </li></ul><ul><ul><li>Stations </li></ul></ul><ul><ul><li>Routes </li></ul></ul>
    42. 42. <ul><li>SELECT rs.Name, rs.Operator, s.Name AS StationName </li></ul><ul><li>FROM RailService AS rs </li></ul><ul><li>INNER JOIN Station AS s ON s.Location.STIntersects(rs.Route) = 1 </li></ul><ul><li>WHERE rs.Name='Edinburgh - Queen Street' </li></ul><ul><li>Name Operator StationName </li></ul><ul><li>------------------------- --------------- --------------------------- </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Croy </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Bishopbriggs </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Falkirk High </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Edinburgh Waverley Station </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Linlithgow </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Lenzie </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Haymarket </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Polmont </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail Queen Street </li></ul>
    43. 43. <ul><li>SELECT s.Name, s.Location.STDistance(st.Location) / 1000.0 AS DistKM </li></ul><ul><li>FROM RailService AS rs </li></ul><ul><li>INNER JOIN Station AS s ON s.Location.STIntersects(rs.Route) = 1 </li></ul><ul><li>INNER JOIN Station AS st ON rs.EndPoint1StationId = st.Id </li></ul><ul><li>WHERE rs.Name='Edinburgh - Queen Street' </li></ul><ul><li>ORDER BY s.Location.STDistance(st.Location) </li></ul><ul><li>Name DistKM </li></ul><ul><li>-------------------------- ----------------- </li></ul><ul><li>Edinburgh Waverley Station 0 </li></ul><ul><li>Haymarket 1.89298770395887 </li></ul><ul><li>Linlithgow 25.330363556826 </li></ul><ul><li>Polmont 32.9442879992987 </li></ul><ul><li>Falkirk High 37.8121663726382 </li></ul><ul><li>Croy 52.7800190223697 </li></ul><ul><li>Lenzie 60.3440166609702 </li></ul><ul><li>Bishopbriggs 64.8149950514336 </li></ul><ul><li>Queen Street 67.0874880660717 </li></ul>
    44. 44. <ul><li>Edinburgh - Glenrothes (via Kirkcaldy) </li></ul><ul><li>Name DistKM </li></ul><ul><li>-------------------------- ---------------- </li></ul><ul><li>Edinburgh Waverley Station 0 </li></ul><ul><li>Haymarket 1.89298770395887 </li></ul><ul><li>South Gyle 6.95446540329848 </li></ul><ul><li>Burntisland 12.086984317701 </li></ul><ul><li>Dalmeny 12.49585147351 </li></ul><ul><li>Kinghorn 13.1439998546632 </li></ul><ul><li>Aberdour 13.3392361220632 </li></ul><ul><li>North Queensferry 14.3833962761344 </li></ul><ul><li>Dalgety Bay 15.0082794626365 </li></ul><ul><li>Inverkeithing 15.7316327831032 </li></ul><ul><li>Kirkcaldy 17.9484646860063 </li></ul><ul><li>Glenrothes With Thornton 23.7022936117453 </li></ul>
    45. 45. <ul><li>Works close to Queen Street Station </li></ul><ul><ul><li>Wants to take the train to work </li></ul></ul><ul><li>SELECT rs.Name, rs.Operator </li></ul><ul><li>FROM RailService AS rs </li></ul><ul><li>INNER JOIN Station AS s ON rs.Route.STIntersects( s.Location) = 1 </li></ul><ul><li>WHERE s.Name = 'Queen Street' </li></ul><ul><li>Name Operator </li></ul><ul><li>----------------------------------- ------------- </li></ul><ul><li>Edinburgh - Queen Street FirstScotRail </li></ul><ul><li>Queen Street - Perth FirstScotRail </li></ul><ul><li>Queen Street - Alloa FirstScotRail </li></ul><ul><li>Queen Street - Inverness FirstScotRail </li></ul><ul><li>Kirkcaldy - Glasgow Queen Street FirstScotRail </li></ul><ul><li>Queen Street - Mallaig FirstScotRail </li></ul><ul><li>Dalmuir - Springburn SPT </li></ul><ul><li>Balloch - Airdrie SPT </li></ul><ul><li>Helensburgh Central - Drumgelloch SPT </li></ul><ul><li>Queen Street - Anniesland SPT </li></ul>
    46. 46. <ul><li>Get all the stations on routes that have a stop at Queen Street </li></ul><ul><li>SELECT DISTINCT ps.Name </li></ul><ul><li>FROM RailService AS rs </li></ul><ul><li>INNER JOIN Station AS s ON rs.Route.STIntersects(s.Location) = 1 </li></ul><ul><li>INNER JOIN Station AS ps ON rs.Route.STIntersects(ps.Location) = 1 </li></ul><ul><li>WHERE s.Name = 'Queen Street' </li></ul>
    47. 47. <ul><li>Buffer 500m around relevant stations </li></ul><ul><li>Need to aggregate the buffered points </li></ul><ul><ul><li>Not built in </li></ul></ul><ul><ul><li>CLR Aggregator? </li></ul></ul><ul><ul><li>Cursor ?!? </li></ul></ul><ul><li>STBuffer(double) </li></ul><ul><ul><li>Param is the distance in metres. </li></ul></ul>
    48. 49. <ul><li>Decomposes space into 4 levels of grid </li></ul><ul><li>Level 1 is the top </li></ul><ul><li>Cells are uniform in a level </li></ul><ul><li>A level can be a 4x4, 8x8 or 16x16 grid </li></ul><ul><ul><li>8x8 by default </li></ul></ul>
    49. 50. <ul><li>Table must have a primary key </li></ul><ul><li>Primary key cannot subsequently be changed. </li></ul><ul><li>Not on views </li></ul><ul><li>Maximum of 249 Spatial indexes per column </li></ul>
    50. 51. <ul><li>Supports </li></ul><ul><ul><li>STIntersects </li></ul></ul><ul><ul><li>STEquals </li></ul></ul><ul><ul><li>STDistance </li></ul></ul><ul><ul><ul><li>One Geography must be a point </li></ul></ul></ul><ul><li>Both sides of the spatial operation must have the same SRID </li></ul>
    51. 52. <ul><li>Must specify boundary of spatial area </li></ul><ul><li>Additional methods supported </li></ul><ul><ul><li>STContains </li></ul></ul><ul><ul><li>STOverlaps </li></ul></ul><ul><ul><li>STTouches </li></ul></ul><ul><ul><li>STWithin </li></ul></ul>
    52. 53. <ul><li>GML </li></ul><ul><ul><li>Import and export </li></ul></ul><ul><li>M and Z </li></ul><ul><ul><li>Can store </li></ul></ul><ul><ul><li>Cannot operate. </li></ul></ul><ul><li>Other spatial Operations </li></ul><ul><ul><li>Geometry has more! </li></ul></ul><ul><li>Visualisation </li></ul><ul><li>.NET application integration </li></ul><ul><li>Data Importing </li></ul><ul><li>Demos </li></ul>
    53. 54. <ul><li>I want to know </li></ul><ul><ul><li>What additional things you’d like covered </li></ul></ul>
    54. 55. <ul><li>Slide Deck on my website </li></ul><ul><ul><li>http://www.colinmackay.net </li></ul></ul><ul><li>Blog posts on Spatial Data </li></ul><ul><ul><li>http://blog.colinmackay.net </li></ul></ul>

    ×